--- /dev/null
+From 90c6e8c5b5942e599d4df5917aaca147b18d530c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Jul 2022 17:26:29 -0400
+Subject: __follow_mount_rcu(): verify that mount_lock remains unchanged
+
+From: Al Viro <viro@zeniv.linux.org.uk>
+
+[ Upstream commit 20aac6c60981f5bfacd66661d090d907bf1482f0 ]
+
+Validate mount_lock seqcount as soon as we cross into mount in RCU
+mode. Sure, ->mnt_root is pinned and will remain so until we
+do rcu_read_unlock() anyway, and we will eventually fail to unlazy if
+the mount_lock had been touched, but we might run into a hard error
+(e.g. -ENOENT) before trying to unlazy. And it's possible to end
+up with RCU pathwalk racing with rename() and umount() in a way
+that would fail with -ENOENT while non-RCU pathwalk would've
+succeeded with any timings.
+
+Once upon a time we hadn't needed that, but analysis had been subtle,
+brittle and went out of window as soon as RENAME_EXCHANGE had been
+added.
+
+It's narrow, hard to hit and won't get you anything other than
+stray -ENOENT that could be arranged in much easier way with the
+same priveleges, but it's a bug all the same.
+
+Cc: stable@kernel.org
+X-sky-is-falling: unlikely
+Fixes: da1ce0670c14 "vfs: add cross-rename"
+Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/namei.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/fs/namei.c b/fs/namei.c
+index 96491f092a99..eba2f13d229d 100644
+--- a/fs/namei.c
++++ b/fs/namei.c
+@@ -1348,6 +1348,8 @@ static bool __follow_mount_rcu(struct nameidata *nd, struct path *path,
+ * becoming unpinned.
+ */
+ flags = dentry->d_flags;
++ if (read_seqretry(&mount_lock, nd->m_seq))
++ return false;
+ continue;
+ }
+ if (read_seqretry(&mount_lock, nd->m_seq))
+--
+2.35.1
+
--- /dev/null
+From f2bbe1aab9d0cde2edb660bb8a0b70a4d6b64ca1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 21 Jul 2022 19:41:10 +0200
+Subject: ACPI: CPPC: Do not prevent CPPC from working in the future
+
+From: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+
+[ Upstream commit 4f4179fcf420873002035cf1941d844c9e0e7cb3 ]
+
+There is a problem with the current revision checks in
+is_cppc_supported() that they essentially prevent the CPPC support
+from working if a new _CPC package format revision being a proper
+superset of the v3 and only causing _CPC to return a package with more
+entries (while retaining the types and meaning of the entries defined by
+the v3) is introduced in the future and used by the platform firmware.
+
+In that case, as long as the number of entries in the _CPC return
+package is at least CPPC_V3_NUM_ENT, it should be perfectly fine to
+use the v3 support code and disregard the additional package entries
+added by the new package format revision.
+
+For this reason, drop is_cppc_supported() altogether, put the revision
+checks directly into acpi_cppc_processor_probe() so they are easier to
+follow and rework them to take the case mentioned above into account.
+
+Fixes: 4773e77cdc9b ("ACPI / CPPC: Add support for CPPC v3")
+Cc: 4.18+ <stable@vger.kernel.org> # 4.18+
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/acpi/cppc_acpi.c | 54 ++++++++++++++++++----------------------
+ include/acpi/cppc_acpi.h | 2 +-
+ 2 files changed, 25 insertions(+), 31 deletions(-)
+
+diff --git a/drivers/acpi/cppc_acpi.c b/drivers/acpi/cppc_acpi.c
+index 2ac0773326e9..b62348a7e4d9 100644
+--- a/drivers/acpi/cppc_acpi.c
++++ b/drivers/acpi/cppc_acpi.c
+@@ -607,33 +607,6 @@ static int pcc_data_alloc(int pcc_ss_id)
+ 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.
+ *
+@@ -729,7 +702,6 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
+ cpc_obj->type);
+ goto out_free;
+ }
+- cpc_ptr->num_entries = num_ent;
+
+ /* Second entry should be revision. */
+ cpc_obj = &out_obj->package.elements[1];
+@@ -740,10 +712,32 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
+ 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++) {
+diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h
+index a6a9373ab863..d9417abf4cd0 100644
+--- a/include/acpi/cppc_acpi.h
++++ b/include/acpi/cppc_acpi.h
+@@ -16,7 +16,7 @@
+ #include <acpi/pcc.h>
+ #include <acpi/processor.h>
+
+-/* Support CPPCv2 and CPPCv3 */
++/* CPPCv2 and CPPCv3 support */
+ #define CPPC_V2_REV 2
+ #define CPPC_V3_REV 3
+ #define CPPC_V2_NUM_ENT 21
+--
+2.35.1
+
--- /dev/null
+From b6aa6ae8a77d31ad0cd39652a04d0467b60ae57d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jun 2022 19:48:24 +0800
+Subject: btrfs: reject log replay if there is unsupported RO compat flag
+
+From: Qu Wenruo <wqu@suse.com>
+
+[ Upstream commit dc4d31684974d140250f3ee612c3f0cab13b3146 ]
+
+[BUG]
+If we have a btrfs image with dirty log, along with an unsupported RO
+compatible flag:
+
+log_root 30474240
+...
+compat_flags 0x0
+compat_ro_flags 0x40000003
+ ( FREE_SPACE_TREE |
+ FREE_SPACE_TREE_VALID |
+ unknown flag: 0x40000000 )
+
+Then even if we can only mount it RO, we will still cause metadata
+update for log replay:
+
+ BTRFS info (device dm-1): flagging fs with big metadata feature
+ BTRFS info (device dm-1): using free space tree
+ BTRFS info (device dm-1): has skinny extents
+ BTRFS info (device dm-1): start tree-log replay
+
+This is definitely against RO compact flag requirement.
+
+[CAUSE]
+RO compact flag only forces us to do RO mount, but we will still do log
+replay for plain RO mount.
+
+Thus this will result us to do log replay and update metadata.
+
+This can be very problematic for new RO compat flag, for example older
+kernel can not understand v2 cache, and if we allow metadata update on
+RO mount and invalidate/corrupt v2 cache.
+
+[FIX]
+Just reject the mount unless rescue=nologreplay is provided:
+
+ BTRFS error (device dm-1): cannot replay dirty log with unsupport optional features (0x40000000), try rescue=nologreplay instead
+
+We don't want to set rescue=nologreply directly, as this would make the
+end user to read the old data, and cause confusion.
+
+Since the such case is really rare, we're mostly fine to just reject the
+mount with an error message, which also includes the proper workaround.
+
+CC: stable@vger.kernel.org #4.9+
+Signed-off-by: Qu Wenruo <wqu@suse.com>
+Reviewed-by: David Sterba <dsterba@suse.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/disk-io.c | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
+index 35acdab56a1c..2c7e50980a70 100644
+--- a/fs/btrfs/disk-io.c
++++ b/fs/btrfs/disk-io.c
+@@ -3104,6 +3104,20 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
+ err = -EINVAL;
+ goto fail_alloc;
+ }
++ /*
++ * We have unsupported RO compat features, although RO mounted, we
++ * should not cause any metadata write, including log replay.
++ * Or we could screw up whatever the new feature requires.
++ */
++ if (unlikely(features && btrfs_super_log_root(disk_super) &&
++ !btrfs_test_opt(fs_info, NOLOGREPLAY))) {
++ btrfs_err(fs_info,
++"cannot replay dirty log with unsupported compat_ro features (0x%llx), try rescue=nologreplay",
++ features);
++ err = -EINVAL;
++ goto fail_alloc;
++ }
++
+
+ ret = btrfs_init_workqueues(fs_info, fs_devices);
+ if (ret) {
+--
+2.35.1
+
--- /dev/null
+From 7571d5dd0a26d5d3be0155c12bb552ff4a80193d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jun 2022 18:31:17 -0400
+Subject: btrfs: reset block group chunk force if we have to wait
+
+From: Josef Bacik <josef@toxicpanda.com>
+
+[ Upstream commit 1314ca78b2c35d3e7d0f097268a2ee6dc0d369ef ]
+
+If you try to force a chunk allocation, but you race with another chunk
+allocation, you will end up waiting on the chunk allocation that just
+occurred and then allocate another chunk. If you have many threads all
+doing this at once you can way over-allocate chunks.
+
+Fix this by resetting force to NO_FORCE, that way if we think we need to
+allocate we can, otherwise we don't force another chunk allocation if
+one is already happening.
+
+Reviewed-by: Filipe Manana <fdmanana@suse.com>
+CC: stable@vger.kernel.org # 5.4+
+Signed-off-by: Josef Bacik <josef@toxicpanda.com>
+Signed-off-by: David Sterba <dsterba@suse.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ fs/btrfs/block-group.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
+index e351f5319950..889a598b17f6 100644
+--- a/fs/btrfs/block-group.c
++++ b/fs/btrfs/block-group.c
+@@ -3126,6 +3126,7 @@ int btrfs_chunk_alloc(struct btrfs_trans_handle *trans, u64 flags,
+ * attempt.
+ */
+ wait_for_alloc = true;
++ force = CHUNK_ALLOC_NO_FORCE;
+ spin_unlock(&space_info->lock);
+ mutex_lock(&fs_info->chunk_mutex);
+ mutex_unlock(&fs_info->chunk_mutex);
+--
+2.35.1
+
--- /dev/null
+From bf9c3bd43bd03414a79b4e5b8e8a1e95c4cd3766 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Jul 2022 19:28:25 +0800
+Subject: dm thin: fix use-after-free crash in
+ dm_sm_register_threshold_callback
+
+From: Luo Meng <luomeng12@huawei.com>
+
+[ Upstream commit 3534e5a5ed2997ca1b00f44a0378a075bd05e8a3 ]
+
+Fault inject on pool metadata device reports:
+ BUG: KASAN: use-after-free in dm_pool_register_metadata_threshold+0x40/0x80
+ Read of size 8 at addr ffff8881b9d50068 by task dmsetup/950
+
+ CPU: 7 PID: 950 Comm: dmsetup Tainted: G W 5.19.0-rc6 #1
+ Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-1.fc33 04/01/2014
+ Call Trace:
+ <TASK>
+ dump_stack_lvl+0x34/0x44
+ print_address_description.constprop.0.cold+0xeb/0x3f4
+ kasan_report.cold+0xe6/0x147
+ dm_pool_register_metadata_threshold+0x40/0x80
+ pool_ctr+0xa0a/0x1150
+ dm_table_add_target+0x2c8/0x640
+ table_load+0x1fd/0x430
+ ctl_ioctl+0x2c4/0x5a0
+ dm_ctl_ioctl+0xa/0x10
+ __x64_sys_ioctl+0xb3/0xd0
+ do_syscall_64+0x35/0x80
+ entry_SYSCALL_64_after_hwframe+0x46/0xb0
+
+This can be easily reproduced using:
+ echo offline > /sys/block/sda/device/state
+ dd if=/dev/zero of=/dev/mapper/thin bs=4k count=10
+ dmsetup load pool --table "0 20971520 thin-pool /dev/sda /dev/sdb 128 0 0"
+
+If a metadata commit fails, the transaction will be aborted and the
+metadata space maps will be destroyed. If a DM table reload then
+happens for this failed thin-pool, a use-after-free will occur in
+dm_sm_register_threshold_callback (called from
+dm_pool_register_metadata_threshold).
+
+Fix this by in dm_pool_register_metadata_threshold() by returning the
+-EINVAL error if the thin-pool is in fail mode. Also fail pool_ctr()
+with a new error message: "Error registering metadata threshold".
+
+Fixes: ac8c3f3df65e4 ("dm thin: generate event when metadata threshold passed")
+Cc: stable@vger.kernel.org
+Reported-by: Hulk Robot <hulkci@huawei.com>
+Signed-off-by: Luo Meng <luomeng12@huawei.com>
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-thin-metadata.c | 7 +++++--
+ drivers/md/dm-thin.c | 4 +++-
+ 2 files changed, 8 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/md/dm-thin-metadata.c b/drivers/md/dm-thin-metadata.c
+index 6ebb2127f3e2..842d79e5ea3a 100644
+--- a/drivers/md/dm-thin-metadata.c
++++ b/drivers/md/dm-thin-metadata.c
+@@ -2058,10 +2058,13 @@ int dm_pool_register_metadata_threshold(struct dm_pool_metadata *pmd,
+ 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;
+diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
+index fff4c50df74d..a196d7cb51bd 100644
+--- a/drivers/md/dm-thin.c
++++ b/drivers/md/dm-thin.c
+@@ -3401,8 +3401,10 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
+ calc_metadata_threshold(pt),
+ metadata_low_callback,
+ pool);
+- if (r)
++ if (r) {
++ ti->error = "Error registering metadata threshold";
+ goto out_flags_changed;
++ }
+
+ dm_pool_register_pre_commit_callback(pool->pmd,
+ metadata_pre_commit_callback, pool);
+--
+2.35.1
+
--- /dev/null
+From 802e1140e1bedeae726496731ab706e5667e697c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Jul 2022 07:09:04 -0400
+Subject: dm writecache: set a default MAX_WRITEBACK_JOBS
+
+From: Mikulas Patocka <mpatocka@redhat.com>
+
+[ Upstream commit ca7dc242e358e46d963b32f9d9dd829785a9e957 ]
+
+dm-writecache has the capability to limit the number of writeback jobs
+in progress. However, this feature was off by default. As such there
+were some out-of-memory crashes observed when lowering the low
+watermark while the cache is full.
+
+This commit enables writeback limit by default. It is set to 256MiB or
+1/16 of total system memory, whichever is smaller.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-writecache.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/md/dm-writecache.c b/drivers/md/dm-writecache.c
+index 9d6ae3e64285..13cc318db012 100644
+--- a/drivers/md/dm-writecache.c
++++ b/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
+--
+2.35.1
+
--- /dev/null
+From 772cf8174eb365b14198007e636d5ff7128e068e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 11 Feb 2022 08:29:33 +0800
+Subject: drm/i915/dg1: Update DMC_DEBUG3 register
+
+From: Chuansheng Liu <chuansheng.liu@intel.com>
+
+[ Upstream commit b60668cb4c57a7cc451de781ae49f5e9cc375eaf ]
+
+Current DMC_DEBUG3(_MMIO(0x101090)) address is for TGL,
+it is wrong for DG1. Just like commit 5bcc95ca382e
+("drm/i915/dg1: Update DMC_DEBUG register"), correct
+this issue for DG1 platform to avoid wrong register
+being read.
+
+BSpec: 49788
+
+v2: fix "not wrong" typo. (Jani)
+
+Reviewed-by: Matt Roper <matthew.d.roper@intel.com>
+Cc: Jani Nikula <jani.nikula@intel.com>
+Signed-off-by: Chuansheng Liu <chuansheng.liu@intel.com>
+Signed-off-by: Matt Roper <matthew.d.roper@intel.com>
+Link: https://patchwork.freedesktop.org/patch/msgid/20220211002933.84240-1-chuansheng.liu@intel.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/i915/display/intel_display_debugfs.c | 4 ++--
+ drivers/gpu/drm/i915/i915_reg.h | 3 ++-
+ 2 files changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/gpu/drm/i915/display/intel_display_debugfs.c b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+index 0bf31f9a8af5..e6780fcc5006 100644
+--- a/drivers/gpu/drm/i915/display/intel_display_debugfs.c
++++ b/drivers/gpu/drm/i915/display/intel_display_debugfs.c
+@@ -526,8 +526,8 @@ static int i915_dmc_info(struct seq_file *m, void *unused)
+ * reg for DC3CO debugging and validation,
+ * but TGL DMC f/w is using DMC_DEBUG3 reg for DC3CO counter.
+ */
+- seq_printf(m, "DC3CO count: %d\n",
+- intel_de_read(dev_priv, DMC_DEBUG3));
++ seq_printf(m, "DC3CO count: %d\n", intel_de_read(dev_priv, IS_DGFX(dev_priv) ?
++ DG1_DMC_DEBUG3 : TGL_DMC_DEBUG3));
+ } else {
+ dc5_reg = IS_BROXTON(dev_priv) ? BXT_CSR_DC3_DC5_COUNT :
+ SKL_CSR_DC3_DC5_COUNT;
+diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
+index f1ab26307db6..04157d8ced32 100644
+--- a/drivers/gpu/drm/i915/i915_reg.h
++++ b/drivers/gpu/drm/i915/i915_reg.h
+@@ -7546,7 +7546,8 @@ enum {
+ #define TGL_DMC_DEBUG_DC5_COUNT _MMIO(0x101084)
+ #define TGL_DMC_DEBUG_DC6_COUNT _MMIO(0x101088)
+
+-#define DMC_DEBUG3 _MMIO(0x101090)
++#define TGL_DMC_DEBUG3 _MMIO(0x101090)
++#define DG1_DMC_DEBUG3 _MMIO(0x13415c)
+
+ /* Display Internal Timeout Register */
+ #define RM_TIMEOUT _MMIO(0x42060)
+--
+2.35.1
+
--- /dev/null
+From 8333bcc1d7343b3de839cc57cade5f93f5fa15cf Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 14 Feb 2022 10:27:42 +0100
+Subject: drm/mediatek: Allow commands to be sent during video mode
+
+From: Julien STEPHAN <jstephan@baylibre.com>
+
+[ Upstream commit 81cc7e51c4f1686b71e30046437056ece6b2cb4d ]
+
+Mipi dsi panel drivers can use mipi_dsi_dcs_{set,get}_display_brightness()
+to request backlight changes.
+
+This can be done during panel initialization (dsi is in command mode)
+or afterwards (dsi is in Video Mode).
+
+When the DSI is in Video Mode, all commands are rejected.
+
+Detect current DSI mode in mtk_dsi_host_transfer() and switch modes
+temporarily to allow commands to be sent.
+
+Signed-off-by: Julien STEPHAN <jstephan@baylibre.com>
+Signed-off-by: Mattijs Korpershoek <mkorpershoek@baylibre.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dsi.c | 33 ++++++++++++++++++++++--------
+ 1 file changed, 24 insertions(+), 9 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
+index f39785934999..9d54bb6aec30 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
+@@ -910,24 +910,33 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
+ u8 read_data[16];
+ void *src_addr;
+ u8 irq_flag = CMD_DONE_INT_FLAG;
++ u32 dsi_mode;
++ int ret;
+
+- if (readl(dsi->regs + DSI_MODE_CTRL) & MODE) {
+- DRM_ERROR("dsi engine is not command mode\n");
+- return -EINVAL;
++ dsi_mode = readl(dsi->regs + DSI_MODE_CTRL);
++ if (dsi_mode & MODE) {
++ mtk_dsi_stop(dsi);
++ ret = mtk_dsi_switch_to_cmd_mode(dsi, VM_DONE_INT_FLAG, 500);
++ if (ret)
++ goto restore_dsi_mode;
+ }
+
+ if (MTK_DSI_HOST_IS_READ(msg->type))
+ irq_flag |= LPRX_RD_RDY_INT_FLAG;
+
+- if (mtk_dsi_host_send_cmd(dsi, msg, irq_flag) < 0)
+- return -ETIME;
++ ret = mtk_dsi_host_send_cmd(dsi, msg, irq_flag);
++ if (ret)
++ goto restore_dsi_mode;
+
+- if (!MTK_DSI_HOST_IS_READ(msg->type))
+- return 0;
++ if (!MTK_DSI_HOST_IS_READ(msg->type)) {
++ recv_cnt = 0;
++ goto restore_dsi_mode;
++ }
+
+ if (!msg->rx_buf) {
+ DRM_ERROR("dsi receive buffer size may be NULL\n");
+- return -EINVAL;
++ ret = -EINVAL;
++ goto restore_dsi_mode;
+ }
+
+ for (i = 0; i < 16; i++)
+@@ -952,7 +961,13 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
+ DRM_INFO("dsi get %d byte data from the panel address(0x%x)\n",
+ recv_cnt, *((u8 *)(msg->tx_buf)));
+
+- return recv_cnt;
++restore_dsi_mode:
++ if (dsi_mode & MODE) {
++ mtk_dsi_set_mode(dsi);
++ mtk_dsi_start(dsi);
++ }
++
++ return ret < 0 ? ret : recv_cnt;
+ }
+
+ static const struct mipi_dsi_host_ops mtk_dsi_ops = {
+--
+2.35.1
+
--- /dev/null
+From c50e2ce294336479f3376f74d25d8f1bcba89dda Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 May 2022 10:00:06 +0800
+Subject: drm/mediatek: Keep dsi as LP00 before dcs cmds transfer
+
+From: Jitao Shi <jitao.shi@mediatek.com>
+
+[ Upstream commit 39e8d062b03c3dc257d880d82bd55cdd9e185a3b ]
+
+To comply with the panel sequence, hold the mipi signal to LP00 before
+the dcs cmds transmission, and pull the mipi signal high from LP00 to
+LP11 until the start of the dcs cmds transmission.
+
+The normal panel timing is :
+(1) pp1800 DC pull up
+(2) avdd & avee AC pull high
+(3) lcm_reset pull high -> pull low -> pull high
+(4) Pull MIPI signal high (LP11) -> initial code -> send video data
+ (HS mode)
+
+The power-off sequence is reversed.
+If dsi is not in cmd mode, then dsi will pull the mipi signal high in
+the mtk_output_dsi_enable function. The delay in lane_ready func is
+the reaction time of dsi_rx after pulling up the mipi signal.
+
+Fixes: 2dd8075d2185 ("drm/mediatek: mtk_dsi: Use the drm_panel_bridge API")
+
+Link: https://patchwork.kernel.org/project/linux-mediatek/patch/1653012007-11854-4-git-send-email-xinlei.lee@mediatek.com/
+Cc: <stable@vger.kernel.org> # 5.10.x: 7f6335c6a258: drm/mediatek: Modify dsi funcs to atomic operations
+Cc: <stable@vger.kernel.org> # 5.10.x: cde7e2e35c28: drm/mediatek: Separate poweron/poweroff from enable/disable and define new funcs
+Cc: <stable@vger.kernel.org> # 5.10.x
+Signed-off-by: Jitao Shi <jitao.shi@mediatek.com>
+Signed-off-by: Xinlei Lee <xinlei.lee@mediatek.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Reviewed-by: Rex-BC Chen <rex-bc.chen@mediatek.com>
+Signed-off-by: Chun-Kuang Hu <chunkuang.hu@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/mediatek/mtk_dsi.c | 28 +++++++++++++++++++++-------
+ 1 file changed, 21 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/gpu/drm/mediatek/mtk_dsi.c b/drivers/gpu/drm/mediatek/mtk_dsi.c
+index 9d54bb6aec30..7d37d2a01e3c 100644
+--- a/drivers/gpu/drm/mediatek/mtk_dsi.c
++++ b/drivers/gpu/drm/mediatek/mtk_dsi.c
+@@ -202,6 +202,7 @@ struct mtk_dsi {
+ struct mtk_phy_timing phy_timing;
+ int refcount;
+ bool enabled;
++ bool lanes_ready;
+ u32 irq_data;
+ wait_queue_head_t irq_wait_queue;
+ const struct mtk_dsi_driver_data *driver_data;
+@@ -644,18 +645,11 @@ static int mtk_dsi_poweron(struct mtk_dsi *dsi)
+ mtk_dsi_reset_engine(dsi);
+ mtk_dsi_phy_timconfig(dsi);
+
+- mtk_dsi_rxtx_control(dsi);
+- usleep_range(30, 100);
+- mtk_dsi_reset_dphy(dsi);
+ mtk_dsi_ps_control_vact(dsi);
+ mtk_dsi_set_vm_cmd(dsi);
+ mtk_dsi_config_vdo_timing(dsi);
+ mtk_dsi_set_interrupt_enable(dsi);
+
+- mtk_dsi_clk_ulp_mode_leave(dsi);
+- mtk_dsi_lane0_ulp_mode_leave(dsi);
+- mtk_dsi_clk_hs_mode(dsi, 0);
+-
+ return 0;
+ err_disable_engine_clk:
+ clk_disable_unprepare(dsi->engine_clk);
+@@ -686,6 +680,23 @@ static void mtk_dsi_poweroff(struct mtk_dsi *dsi)
+ clk_disable_unprepare(dsi->digital_clk);
+
+ phy_power_off(dsi->phy);
++
++ dsi->lanes_ready = false;
++}
++
++static void mtk_dsi_lane_ready(struct mtk_dsi *dsi)
++{
++ if (!dsi->lanes_ready) {
++ dsi->lanes_ready = true;
++ mtk_dsi_rxtx_control(dsi);
++ usleep_range(30, 100);
++ mtk_dsi_reset_dphy(dsi);
++ mtk_dsi_clk_ulp_mode_leave(dsi);
++ mtk_dsi_lane0_ulp_mode_leave(dsi);
++ mtk_dsi_clk_hs_mode(dsi, 0);
++ msleep(20);
++ /* The reaction time after pulling up the mipi signal for dsi_rx */
++ }
+ }
+
+ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
+@@ -693,6 +704,7 @@ static void mtk_output_dsi_enable(struct mtk_dsi *dsi)
+ if (dsi->enabled)
+ return;
+
++ mtk_dsi_lane_ready(dsi);
+ mtk_dsi_set_mode(dsi);
+ mtk_dsi_clk_hs_mode(dsi, 1);
+
+@@ -924,6 +936,8 @@ static ssize_t mtk_dsi_host_transfer(struct mipi_dsi_host *host,
+ if (MTK_DSI_HOST_IS_READ(msg->type))
+ irq_flag |= LPRX_RD_RDY_INT_FLAG;
+
++ mtk_dsi_lane_ready(dsi);
++
+ ret = mtk_dsi_host_send_cmd(dsi, msg, irq_flag);
+ if (ret)
+ goto restore_dsi_mode;
+--
+2.35.1
+
--- /dev/null
+From a845d39182f4d6a6e85d54900fefb5ff0b38f14d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Jun 2022 16:47:28 +0200
+Subject: drm/vc4: drv: Adopt the dma configuration from the HVS or V3D
+ component
+
+From: Dave Stevenson <dave.stevenson@raspberrypi.com>
+
+[ Upstream commit da8e393e23efb60eba8959856c7df88f9859f6eb ]
+
+vc4_drv isn't necessarily under the /soc node in DT as it is a
+virtual device, but it is the one that does the allocations.
+The DMA addresses are consumed by primarily the HVS or V3D, and
+those require VideoCore cache alias address mapping, and so will be
+under /soc.
+
+During probe find the a suitable device node for HVS or V3D,
+and adopt the DMA configuration of that node.
+
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
+Link: https://lore.kernel.org/r/20220613144800.326124-2-maxime@cerno.tech
+Signed-off-by: Maxime Ripard <maxime@cerno.tech>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/vc4/vc4_drv.c | 19 +++++++++++++++++++
+ 1 file changed, 19 insertions(+)
+
+diff --git a/drivers/gpu/drm/vc4/vc4_drv.c b/drivers/gpu/drm/vc4/vc4_drv.c
+index 839610f8092a..4bed62916b64 100644
+--- a/drivers/gpu/drm/vc4/vc4_drv.c
++++ b/drivers/gpu/drm/vc4/vc4_drv.c
+@@ -246,6 +246,15 @@ static void vc4_match_add_drivers(struct device *dev,
+ }
+ }
+
++const struct of_device_id vc4_dma_range_matches[] = {
++ { .compatible = "brcm,bcm2711-hvs" },
++ { .compatible = "brcm,bcm2835-hvs" },
++ { .compatible = "brcm,bcm2835-v3d" },
++ { .compatible = "brcm,cygnus-v3d" },
++ { .compatible = "brcm,vc4-v3d" },
++ {}
++};
++
+ static int vc4_drm_bind(struct device *dev)
+ {
+ struct platform_device *pdev = to_platform_device(dev);
+@@ -263,6 +272,16 @@ static int vc4_drm_bind(struct device *dev)
+ vc4_drm_driver.driver_features &= ~DRIVER_RENDER;
+ of_node_put(node);
+
++ node = of_find_matching_node_and_match(NULL, vc4_dma_range_matches,
++ NULL);
++ if (node) {
++ ret = of_dma_configure(dev, node, true);
++ of_node_put(node);
++
++ if (ret)
++ return ret;
++ }
++
+ vc4 = devm_drm_dev_alloc(dev, &vc4_drm_driver, struct vc4_dev, base);
+ if (IS_ERR(vc4))
+ return PTR_ERR(vc4);
+--
+2.35.1
+
--- /dev/null
+From df29133b2692e2b075f7a4e44d4d6bc44df6015b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 1 Jul 2022 17:03:10 +0100
+Subject: firmware: arm_scpi: Ensure scpi_info is not assigned if the probe
+ fails
+
+From: Sudeep Holla <sudeep.holla@arm.com>
+
+[ Upstream commit 689640efc0a2c4e07e6f88affe6d42cd40cc3f85 ]
+
+When scpi probe fails, at any point, we need to ensure that the scpi_info
+is not set and will remain NULL until the probe succeeds. If it is not
+taken care, then it could result use-after-free as the value is exported
+via get_scpi_ops() and could refer to a memory allocated via devm_kzalloc()
+but freed when the probe fails.
+
+Link: https://lore.kernel.org/r/20220701160310.148344-1-sudeep.holla@arm.com
+Cc: stable@vger.kernel.org # 4.19+
+Reported-by: huhai <huhai@kylinos.cn>
+Reviewed-by: Jackie Liu <liuyun01@kylinos.cn>
+Signed-off-by: Sudeep Holla <sudeep.holla@arm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/firmware/arm_scpi.c | 61 +++++++++++++++++++++----------------
+ 1 file changed, 35 insertions(+), 26 deletions(-)
+
+diff --git a/drivers/firmware/arm_scpi.c b/drivers/firmware/arm_scpi.c
+index 4ceba5ef7895..36391cb5130e 100644
+--- a/drivers/firmware/arm_scpi.c
++++ b/drivers/firmware/arm_scpi.c
+@@ -815,7 +815,7 @@ static int scpi_init_versions(struct scpi_drvinfo *info)
+ 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;
+@@ -905,13 +905,14 @@ static int scpi_probe(struct platform_device *pdev)
+ 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) {
+@@ -919,19 +920,19 @@ static int scpi_probe(struct platform_device *pdev)
+ 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);
+
+@@ -975,45 +976,53 @@ static int scpi_probe(struct platform_device *pdev)
+ 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));
++
++ scpi_drvinfo->scpi_ops = &scpi_ops;
+
+- return devm_of_platform_populate(dev);
++ ret = devm_of_platform_populate(dev);
++ if (ret)
++ scpi_info = NULL;
++
++ return ret;
+ }
+
+ static const struct of_device_id scpi_of_match[] = {
+--
+2.35.1
+
--- /dev/null
+From c057e8f67d6f32bc76d1a0a6a7eb44cb894244e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 3 Jun 2021 20:58:14 +0200
+Subject: HID: hid-input: add Surface Go battery quirk
+
+From: Zoltan Tamas Vajda <zoltan.tamas.vajda@gmail.com>
+
+[ Upstream commit b5539722eb832441f309642fe5102cc3536f92b8 ]
+
+The Elantech touchscreen/digitizer in the Surface Go mistakenly reports
+having a battery. This results in a low battery message every time you
+try to use the pen.
+
+This patch adds a quirk to ignore the non-existent battery and
+gets rid of the false low battery messages.
+
+Signed-off-by: Zoltan Tamas Vajda <zoltan.tamas.vajda@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-ids.h | 1 +
+ drivers/hid/hid-input.c | 2 ++
+ 2 files changed, 3 insertions(+)
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index cf69191b6693..bb096dfb7b36 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -391,6 +391,7 @@
+ #define USB_DEVICE_ID_HP_X2_10_COVER 0x0755
+ #define I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817
+ #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706
++#define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A
+
+ #define USB_VENDOR_ID_ELECOM 0x056e
+ #define USB_DEVICE_ID_ELECOM_BM084 0x0061
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index 329b7ffb7e6a..75a4d8d6bb0f 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -326,6 +326,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
+ HID_BATTERY_QUIRK_IGNORE },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15),
+ HID_BATTERY_QUIRK_IGNORE },
++ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN),
++ HID_BATTERY_QUIRK_IGNORE },
+ {}
+ };
+
+--
+2.35.1
+
--- /dev/null
+From e08fbcccbb339f95fc9a3a5ba16adb28dcec55aa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Jan 2021 22:24:37 +0100
+Subject: HID: Ignore battery for Elan touchscreen on HP Spectre X360 15-df0xxx
+
+From: Elia Devito <eliadevito@gmail.com>
+
+[ Upstream commit decfe496fe77061dea658a0bfa11afd4f92b540d ]
+
+Battery status is reported for the HP Spectre X360 Convertible 15-df0xxx
+even if it does not have a battery. Prevent it to always report the
+battery as low.
+
+Signed-off-by: Elia Devito <eliadevito@gmail.com>
+Signed-off-by: Jiri Kosina <jkosina@suse.cz>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hid/hid-ids.h | 1 +
+ drivers/hid/hid-input.c | 2 ++
+ 2 files changed, 3 insertions(+)
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index 3744c3db5140..cf69191b6693 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -389,6 +389,7 @@
+ #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 I2C_DEVICE_ID_HP_SPECTRE_X360_15 0x2817
+ #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706
+
+ #define USB_VENDOR_ID_ELECOM 0x056e
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index a17d1dda9570..329b7ffb7e6a 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -324,6 +324,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
+ HID_BATTERY_QUIRK_IGNORE },
+ { HID_USB_DEVICE(USB_VENDOR_ID_ELAN, USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN),
+ HID_BATTERY_QUIRK_IGNORE },
++ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_HP_SPECTRE_X360_15),
++ HID_BATTERY_QUIRK_IGNORE },
+ {}
+ };
+
+--
+2.35.1
+
--- /dev/null
+From ea38fb2bd1c02afd483ac96de3804c9e2a9f01d1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jul 2022 11:26:35 +0300
+Subject: intel_th: pci: Add Meteor Lake-P support
+
+From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+
+[ Upstream commit 802a9a0b1d91274ef10d9fe429b4cc1e8c200aef ]
+
+Add support for the Trace Hub in Meteor Lake-P.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Link: https://lore.kernel.org/r/20220705082637.59979-5-alexander.shishkin@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/intel_th/pci.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
+index d032c4de9ce6..f9b742c42c35 100644
+--- a/drivers/hwtracing/intel_th/pci.c
++++ b/drivers/hwtracing/intel_th/pci.c
+@@ -284,6 +284,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x54a6),
+ .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,
++ },
+ {
+ /* Alder Lake CPU */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f),
+--
+2.35.1
+
--- /dev/null
+From 5397c08cc7a5094c08c5e7046fa37ef76c3ec76a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jul 2022 11:26:37 +0300
+Subject: intel_th: pci: Add Raptor Lake-S CPU support
+
+From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+
+[ Upstream commit ff46a601afc5a66a81c3945b83d0a2caeb88e8bc ]
+
+Add support for the Trace Hub in Raptor Lake-S CPU.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Link: https://lore.kernel.org/r/20220705082637.59979-7-alexander.shishkin@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/intel_th/pci.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
+index 1b9c294dd5fc..e25438025b9f 100644
+--- a/drivers/hwtracing/intel_th/pci.c
++++ b/drivers/hwtracing/intel_th/pci.c
+@@ -294,6 +294,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7a26),
+ .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,
++ },
+ {
+ /* Alder Lake CPU */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f),
+--
+2.35.1
+
--- /dev/null
+From 4a8a73ef9c697eac3e351c1715132306247e1ae1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Jul 2022 11:26:36 +0300
+Subject: intel_th: pci: Add Raptor Lake-S PCH support
+
+From: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+
+[ Upstream commit 23e2de5826e2fc4dd43e08bab3a2ea1a5338b063 ]
+
+Add support for the Trace Hub in Raptor Lake-S PCH.
+
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Cc: stable <stable@kernel.org>
+Signed-off-by: Alexander Shishkin <alexander.shishkin@linux.intel.com>
+Link: https://lore.kernel.org/r/20220705082637.59979-6-alexander.shishkin@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/hwtracing/intel_th/pci.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/hwtracing/intel_th/pci.c b/drivers/hwtracing/intel_th/pci.c
+index f9b742c42c35..1b9c294dd5fc 100644
+--- a/drivers/hwtracing/intel_th/pci.c
++++ b/drivers/hwtracing/intel_th/pci.c
+@@ -289,6 +289,11 @@ static const struct pci_device_id intel_th_pci_id_table[] = {
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x7e24),
+ .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,
++ },
+ {
+ /* Alder Lake CPU */
+ PCI_DEVICE(PCI_VENDOR_ID_INTEL, 0x466f),
+--
+2.35.1
+
--- /dev/null
+From 61d7e7dc28b76a1564c45dcdb5e81afd39d03387 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 17:38:36 +0200
+Subject: iommu/vt-d: avoid invalid memory access via node_online(NUMA_NO_NODE)
+
+From: Alexander Lobakin <alexandr.lobakin@intel.com>
+
+[ Upstream commit b0b0b77ea611e3088e9523e60860f4f41b62b235 ]
+
+KASAN reports:
+
+[ 4.668325][ T0] BUG: KASAN: wild-memory-access in dmar_parse_one_rhsa (arch/x86/include/asm/bitops.h:214 arch/x86/include/asm/bitops.h:226 include/asm-generic/bitops/instrumented-non-atomic.h:142 include/linux/nodemask.h:415 drivers/iommu/intel/dmar.c:497)
+[ 4.676149][ T0] Read of size 8 at addr 1fffffff85115558 by task swapper/0/0
+[ 4.683454][ T0]
+[ 4.685638][ T0] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 5.19.0-rc3-00004-g0e862838f290 #1
+[ 4.694331][ T0] Hardware name: Supermicro SYS-5018D-FN4T/X10SDV-8C-TLN4F, BIOS 1.1 03/02/2016
+[ 4.703196][ T0] Call Trace:
+[ 4.706334][ T0] <TASK>
+[ 4.709133][ T0] ? dmar_parse_one_rhsa (arch/x86/include/asm/bitops.h:214 arch/x86/include/asm/bitops.h:226 include/asm-generic/bitops/instrumented-non-atomic.h:142 include/linux/nodemask.h:415 drivers/iommu/intel/dmar.c:497)
+
+after converting the type of the first argument (@nr, bit number)
+of arch_test_bit() from `long` to `unsigned long`[0].
+
+Under certain conditions (for example, when ACPI NUMA is disabled
+via command line), pxm_to_node() can return %NUMA_NO_NODE (-1).
+It is valid 'magic' number of NUMA node, but not valid bit number
+to use in bitops.
+node_online() eventually descends to test_bit() without checking
+for the input, assuming it's on caller side (which might be good
+for perf-critical tasks). There, -1 becomes %ULONG_MAX which leads
+to an insane array index when calculating bit position in memory.
+
+For now, add an explicit check for @node being not %NUMA_NO_NODE
+before calling test_bit(). The actual logics didn't change here
+at all.
+
+[0] https://github.com/norov/linux/commit/0e862838f290147ea9c16db852d8d494b552d38d
+
+Fixes: ee34b32d8c29 ("dmar: support for parsing Remapping Hardware Static Affinity structure")
+Cc: stable@vger.kernel.org # 2.6.33+
+Reported-by: kernel test robot <oliver.sang@intel.com>
+Signed-off-by: Alexander Lobakin <alexandr.lobakin@intel.com>
+Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
+Signed-off-by: Yury Norov <yury.norov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/iommu/intel/dmar.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
+index 70d569b80ecf..0bc497f4cb9f 100644
+--- a/drivers/iommu/intel/dmar.c
++++ b/drivers/iommu/intel/dmar.c
+@@ -497,7 +497,7 @@ static int dmar_parse_one_rhsa(struct acpi_dmar_header *header, void *arg)
+ if (drhd->reg_base_addr == rhsa->base_address) {
+ int node = 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;
+--
+2.35.1
+
--- /dev/null
+From 374efb06d1539e2bdd2c69cc812d067683442f5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 Jul 2022 21:40:27 +0800
+Subject: kexec, KEYS, s390: Make use of built-in and secondary keyring for
+ signature verification
+
+From: Michal Suchanek <msuchanek@suse.de>
+
+[ Upstream commit 0828c4a39be57768b8788e8cbd0d84683ea757e5 ]
+
+commit e23a8020ce4e ("s390/kexec_file: Signature verification prototype")
+adds support for KEXEC_SIG verification with keys from platform keyring
+but the built-in keys and secondary keyring are not used.
+
+Add support for the built-in keys and secondary keyring as x86 does.
+
+Fixes: e23a8020ce4e ("s390/kexec_file: Signature verification prototype")
+Cc: stable@vger.kernel.org
+Cc: Philipp Rudo <prudo@linux.ibm.com>
+Cc: kexec@lists.infradead.org
+Cc: keyrings@vger.kernel.org
+Cc: linux-security-module@vger.kernel.org
+Signed-off-by: Michal Suchanek <msuchanek@suse.de>
+Reviewed-by: "Lee, Chun-Yi" <jlee@suse.com>
+Acked-by: Baoquan He <bhe@redhat.com>
+Signed-off-by: Coiby Xu <coxu@redhat.com>
+Acked-by: Heiko Carstens <hca@linux.ibm.com>
+Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/s390/kernel/machine_kexec_file.c | 18 +++++++++++++-----
+ 1 file changed, 13 insertions(+), 5 deletions(-)
+
+diff --git a/arch/s390/kernel/machine_kexec_file.c b/arch/s390/kernel/machine_kexec_file.c
+index 76cd09879eaf..53da174754d9 100644
+--- a/arch/s390/kernel/machine_kexec_file.c
++++ b/arch/s390/kernel/machine_kexec_file.c
+@@ -29,6 +29,7 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len)
+ 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)
+@@ -63,11 +64,18 @@ int s390_verify_sig(const char *kernel, unsigned long kernel_len)
+ 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 */
+
+--
+2.35.1
+
--- /dev/null
+From 9010c28e8113c3c142d67ab57878a564deb7ba5a Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 7 Jun 2022 21:35:52 +0000
+Subject: KVM: nVMX: Inject #UD if VMXON is attempted with incompatible CR0/CR4
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit c7d855c2aff2d511fd60ee2e356134c4fb394799 ]
+
+Inject a #UD if L1 attempts VMXON with a CR0 or CR4 that is disallowed
+per the associated nested VMX MSRs' fixed0/1 settings. KVM cannot rely
+on hardware to perform the checks, even for the few checks that have
+higher priority than VM-Exit, as (a) KVM may have forced CR0/CR4 bits in
+hardware while running the guest, (b) there may incompatible CR0/CR4 bits
+that have lower priority than VM-Exit, e.g. CR0.NE, and (c) userspace may
+have further restricted the allowed CR0/CR4 values by manipulating the
+guest's nested VMX MSRs.
+
+Note, despite a very strong desire to throw shade at Jim, commit
+70f3aac964ae ("kvm: nVMX: Remove superfluous VMX instruction fault checks")
+is not to blame for the buggy behavior (though the comment...). That
+commit only removed the CR0.PE, EFLAGS.VM, and COMPATIBILITY mode checks
+(though it did erroneously drop the CPL check, but that has already been
+remedied). KVM may force CR0.PE=1, but will do so only when also
+forcing EFLAGS.VM=1 to emulate Real Mode, i.e. hardware will still #UD.
+
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=216033
+Fixes: ec378aeef9df ("KVM: nVMX: Implement VMXON and VMXOFF")
+Reported-by: Eric Li <ercli@ucdavis.edu>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20220607213604.3346000-4-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/nested.c | 23 ++++++++++++++---------
+ 1 file changed, 14 insertions(+), 9 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
+index 3228db4db5df..6c4277e99d58 100644
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -4877,20 +4877,25 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
+ | FEAT_CTL_VMX_ENABLED_OUTSIDE_SMX;
+
+ /*
+- * The Intel VMX Instruction Reference lists a bunch of bits that are
+- * prerequisite to running VMXON, most notably cr4.VMXE must be set to
+- * 1 (see vmx_is_valid_cr4() for when we allow the guest to set this).
+- * Otherwise, we should fail with #UD. But most faulting conditions
+- * have already been checked by hardware, prior to the VM-exit for
+- * VMXON. We do test guest cr4.VMXE because processor CR4 always has
+- * that bit set to 1 in non-root mode.
++ * Note, KVM cannot rely on hardware to perform the CR0/CR4 #UD checks
++ * that have higher priority than VM-Exit (see Intel SDM's pseudocode
++ * for VMXON), as KVM must load valid CR0/CR4 values into hardware while
++ * running the guest, i.e. KVM needs to check the _guest_ values.
++ *
++ * Rely on hardware for the other two pre-VM-Exit checks, !VM86 and
++ * !COMPATIBILITY modes. KVM may run the guest in VM86 to emulate Real
++ * Mode, but KVM will never take the guest out of those modes.
+ */
+- if (!kvm_read_cr4_bits(vcpu, X86_CR4_VMXE)) {
++ if (!nested_host_cr0_valid(vcpu, kvm_read_cr0(vcpu)) ||
++ !nested_host_cr4_valid(vcpu, kvm_read_cr4(vcpu))) {
+ kvm_queue_exception(vcpu, UD_VECTOR);
+ return 1;
+ }
+
+- /* CPL=0 must be checked manually. */
++ /*
++ * CPL=0 and all other checks that are lower priority than VM-Exit must
++ * be checked manually.
++ */
+ if (vmx_get_cpl(vcpu)) {
+ kvm_inject_gp(vcpu, 0);
+ return 1;
+--
+2.35.1
+
--- /dev/null
+From c96fa61695d77d8850634a90c916eb2f9b1c1177 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 28 May 2021 19:07:44 +1000
+Subject: KVM: PPC: Book3S HV: Remove virt mode checks from real mode handlers
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Nicholas Piggin <npiggin@gmail.com>
+
+[ Upstream commit dcbac73a5b374873bd6dfd8a0ee5d0b7fc844420 ]
+
+Now that the P7/8 path no longer supports radix, real-mode handlers
+do not need to deal with being called in virt mode.
+
+This change effectively reverts commit acde25726bc6 ("KVM: PPC: Book3S
+HV: Add radix checks in real-mode hypercall handlers").
+
+It removes a few more real-mode tests in rm hcall handlers, which
+allows the indirect ops for the xive module to be removed from the
+built-in xics rm handlers.
+
+kvmppc_h_random is renamed to kvmppc_rm_h_random to be a bit more
+descriptive and consistent with other rm handlers.
+
+Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
+Reviewed-by: Cédric Le Goater <clg@kaod.org>
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20210528090752.3542186-25-npiggin@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/include/asm/kvm_ppc.h | 10 +--
+ arch/powerpc/kvm/book3s.c | 11 +--
+ arch/powerpc/kvm/book3s_64_vio_hv.c | 12 ----
+ arch/powerpc/kvm/book3s_hv_builtin.c | 91 ++++++-------------------
+ arch/powerpc/kvm/book3s_hv_rmhandlers.S | 2 +-
+ arch/powerpc/kvm/book3s_xive.c | 18 -----
+ arch/powerpc/kvm/book3s_xive.h | 7 --
+ arch/powerpc/kvm/book3s_xive_native.c | 10 ---
+ 8 files changed, 23 insertions(+), 138 deletions(-)
+
+diff --git a/arch/powerpc/include/asm/kvm_ppc.h b/arch/powerpc/include/asm/kvm_ppc.h
+index 0a056c64c317..ec18d9b01625 100644
+--- a/arch/powerpc/include/asm/kvm_ppc.h
++++ b/arch/powerpc/include/asm/kvm_ppc.h
+@@ -654,8 +654,6 @@ extern int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
+ u32 *priority);
+ extern int kvmppc_xive_int_on(struct kvm *kvm, u32 irq);
+ extern int kvmppc_xive_int_off(struct kvm *kvm, u32 irq);
+-extern void kvmppc_xive_init_module(void);
+-extern void kvmppc_xive_exit_module(void);
+
+ extern int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
+ struct kvm_vcpu *vcpu, u32 cpu);
+@@ -679,8 +677,6 @@ static inline int kvmppc_xive_enabled(struct kvm_vcpu *vcpu)
+ extern int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
+ struct kvm_vcpu *vcpu, u32 cpu);
+ extern void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu);
+-extern void kvmppc_xive_native_init_module(void);
+-extern void kvmppc_xive_native_exit_module(void);
+ extern int kvmppc_xive_native_get_vp(struct kvm_vcpu *vcpu,
+ union kvmppc_one_reg *val);
+ extern int kvmppc_xive_native_set_vp(struct kvm_vcpu *vcpu,
+@@ -694,8 +690,6 @@ static inline int kvmppc_xive_get_xive(struct kvm *kvm, u32 irq, u32 *server,
+ u32 *priority) { return -1; }
+ static inline int kvmppc_xive_int_on(struct kvm *kvm, u32 irq) { return -1; }
+ static inline int kvmppc_xive_int_off(struct kvm *kvm, u32 irq) { return -1; }
+-static inline void kvmppc_xive_init_module(void) { }
+-static inline void kvmppc_xive_exit_module(void) { }
+
+ static inline int kvmppc_xive_connect_vcpu(struct kvm_device *dev,
+ struct kvm_vcpu *vcpu, u32 cpu) { return -EBUSY; }
+@@ -716,8 +710,6 @@ static inline int kvmppc_xive_enabled(struct kvm_vcpu *vcpu)
+ static inline int kvmppc_xive_native_connect_vcpu(struct kvm_device *dev,
+ struct kvm_vcpu *vcpu, u32 cpu) { return -EBUSY; }
+ static inline void kvmppc_xive_native_cleanup_vcpu(struct kvm_vcpu *vcpu) { }
+-static inline void kvmppc_xive_native_init_module(void) { }
+-static inline void kvmppc_xive_native_exit_module(void) { }
+ static inline int kvmppc_xive_native_get_vp(struct kvm_vcpu *vcpu,
+ union kvmppc_one_reg *val)
+ { return 0; }
+@@ -753,7 +745,7 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
+ unsigned long tce_value, unsigned long npages);
+ long int kvmppc_rm_h_confer(struct kvm_vcpu *vcpu, int target,
+ unsigned int yield_count);
+-long kvmppc_h_random(struct kvm_vcpu *vcpu);
++long kvmppc_rm_h_random(struct kvm_vcpu *vcpu);
+ void kvmhv_commence_exit(int trap);
+ void kvmppc_realmode_machine_check(struct kvm_vcpu *vcpu);
+ void kvmppc_subcore_enter_guest(void);
+diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
+index 44bf567b6589..1888aedfd410 100644
+--- a/arch/powerpc/kvm/book3s.c
++++ b/arch/powerpc/kvm/book3s.c
+@@ -1046,13 +1046,10 @@ static int kvmppc_book3s_init(void)
+ #ifdef CONFIG_KVM_XICS
+ #ifdef CONFIG_KVM_XIVE
+ if (xics_on_xive()) {
+- kvmppc_xive_init_module();
+ kvm_register_device_ops(&kvm_xive_ops, KVM_DEV_TYPE_XICS);
+- if (kvmppc_xive_native_supported()) {
+- kvmppc_xive_native_init_module();
++ if (kvmppc_xive_native_supported())
+ kvm_register_device_ops(&kvm_xive_native_ops,
+ KVM_DEV_TYPE_XIVE);
+- }
+ } else
+ #endif
+ kvm_register_device_ops(&kvm_xics_ops, KVM_DEV_TYPE_XICS);
+@@ -1062,12 +1059,6 @@ static int kvmppc_book3s_init(void)
+
+ static void kvmppc_book3s_exit(void)
+ {
+-#ifdef CONFIG_KVM_XICS
+- if (xics_on_xive()) {
+- kvmppc_xive_exit_module();
+- kvmppc_xive_native_exit_module();
+- }
+-#endif
+ #ifdef CONFIG_KVM_BOOK3S_32_HANDLER
+ kvmppc_book3s_exit_pr();
+ #endif
+diff --git a/arch/powerpc/kvm/book3s_64_vio_hv.c b/arch/powerpc/kvm/book3s_64_vio_hv.c
+index 57af53a6a2d8..5f8573774383 100644
+--- a/arch/powerpc/kvm/book3s_64_vio_hv.c
++++ b/arch/powerpc/kvm/book3s_64_vio_hv.c
+@@ -404,10 +404,6 @@ long kvmppc_rm_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
+ /* udbg_printf("H_PUT_TCE(): liobn=0x%lx ioba=0x%lx, tce=0x%lx\n", */
+ /* liobn, ioba, tce); */
+
+- /* For radix, we might be in virtual mode, so punt */
+- if (kvm_is_radix(vcpu->kvm))
+- return H_TOO_HARD;
+-
+ stt = kvmppc_find_table(vcpu->kvm, liobn);
+ if (!stt)
+ return H_TOO_HARD;
+@@ -500,10 +496,6 @@ long kvmppc_rm_h_put_tce_indirect(struct kvm_vcpu *vcpu,
+ bool prereg = false;
+ struct kvmppc_spapr_tce_iommu_table *stit;
+
+- /* For radix, we might be in virtual mode, so punt */
+- if (kvm_is_radix(vcpu->kvm))
+- return H_TOO_HARD;
+-
+ /*
+ * used to check for invalidations in progress
+ */
+@@ -609,10 +601,6 @@ long kvmppc_rm_h_stuff_tce(struct kvm_vcpu *vcpu,
+ long i, ret;
+ struct kvmppc_spapr_tce_iommu_table *stit;
+
+- /* For radix, we might be in virtual mode, so punt */
+- if (kvm_is_radix(vcpu->kvm))
+- return H_TOO_HARD;
+-
+ stt = kvmppc_find_table(vcpu->kvm, liobn);
+ if (!stt)
+ return H_TOO_HARD;
+diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
+index 121fca2bcd82..856a04ca833c 100644
+--- a/arch/powerpc/kvm/book3s_hv_builtin.c
++++ b/arch/powerpc/kvm/book3s_hv_builtin.c
+@@ -33,21 +33,6 @@
+ #include "book3s_xics.h"
+ #include "book3s_xive.h"
+
+-/*
+- * The XIVE module will populate these when it loads
+- */
+-unsigned long (*__xive_vm_h_xirr)(struct kvm_vcpu *vcpu);
+-unsigned long (*__xive_vm_h_ipoll)(struct kvm_vcpu *vcpu, unsigned long server);
+-int (*__xive_vm_h_ipi)(struct kvm_vcpu *vcpu, unsigned long server,
+- unsigned long mfrr);
+-int (*__xive_vm_h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr);
+-int (*__xive_vm_h_eoi)(struct kvm_vcpu *vcpu, unsigned long xirr);
+-EXPORT_SYMBOL_GPL(__xive_vm_h_xirr);
+-EXPORT_SYMBOL_GPL(__xive_vm_h_ipoll);
+-EXPORT_SYMBOL_GPL(__xive_vm_h_ipi);
+-EXPORT_SYMBOL_GPL(__xive_vm_h_cppr);
+-EXPORT_SYMBOL_GPL(__xive_vm_h_eoi);
+-
+ /*
+ * Hash page table alignment on newer cpus(CPU_FTR_ARCH_206)
+ * should be power of 2.
+@@ -195,16 +180,9 @@ int kvmppc_hwrng_present(void)
+ }
+ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
+
+-long kvmppc_h_random(struct kvm_vcpu *vcpu)
++long kvmppc_rm_h_random(struct kvm_vcpu *vcpu)
+ {
+- int r;
+-
+- /* Only need to do the expensive mfmsr() on radix */
+- if (kvm_is_radix(vcpu->kvm) && (mfmsr() & MSR_IR))
+- r = powernv_get_random_long(&vcpu->arch.regs.gpr[4]);
+- else
+- r = powernv_get_random_real_mode(&vcpu->arch.regs.gpr[4]);
+- if (r)
++ if (powernv_get_random_real_mode(&vcpu->arch.regs.gpr[4]))
+ return H_SUCCESS;
+
+ return H_HARDWARE;
+@@ -557,22 +535,13 @@ static long kvmppc_read_one_intr(bool *again)
+ }
+
+ #ifdef CONFIG_KVM_XICS
+-static inline bool is_rm(void)
+-{
+- return !(mfmsr() & MSR_DR);
+-}
+-
+ unsigned long kvmppc_rm_h_xirr(struct kvm_vcpu *vcpu)
+ {
+ if (!kvmppc_xics_enabled(vcpu))
+ return H_TOO_HARD;
+- if (xics_on_xive()) {
+- if (is_rm())
+- return xive_rm_h_xirr(vcpu);
+- if (unlikely(!__xive_vm_h_xirr))
+- return H_NOT_AVAILABLE;
+- return __xive_vm_h_xirr(vcpu);
+- } else
++ if (xics_on_xive())
++ return xive_rm_h_xirr(vcpu);
++ else
+ return xics_rm_h_xirr(vcpu);
+ }
+
+@@ -581,13 +550,9 @@ unsigned long kvmppc_rm_h_xirr_x(struct kvm_vcpu *vcpu)
+ if (!kvmppc_xics_enabled(vcpu))
+ return H_TOO_HARD;
+ vcpu->arch.regs.gpr[5] = get_tb();
+- if (xics_on_xive()) {
+- if (is_rm())
+- return xive_rm_h_xirr(vcpu);
+- if (unlikely(!__xive_vm_h_xirr))
+- return H_NOT_AVAILABLE;
+- return __xive_vm_h_xirr(vcpu);
+- } else
++ if (xics_on_xive())
++ return xive_rm_h_xirr(vcpu);
++ else
+ return xics_rm_h_xirr(vcpu);
+ }
+
+@@ -595,13 +560,9 @@ unsigned long kvmppc_rm_h_ipoll(struct kvm_vcpu *vcpu, unsigned long server)
+ {
+ if (!kvmppc_xics_enabled(vcpu))
+ return H_TOO_HARD;
+- if (xics_on_xive()) {
+- if (is_rm())
+- return xive_rm_h_ipoll(vcpu, server);
+- if (unlikely(!__xive_vm_h_ipoll))
+- return H_NOT_AVAILABLE;
+- return __xive_vm_h_ipoll(vcpu, server);
+- } else
++ if (xics_on_xive())
++ return xive_rm_h_ipoll(vcpu, server);
++ else
+ return H_TOO_HARD;
+ }
+
+@@ -610,13 +571,9 @@ int kvmppc_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
+ {
+ if (!kvmppc_xics_enabled(vcpu))
+ return H_TOO_HARD;
+- if (xics_on_xive()) {
+- if (is_rm())
+- return xive_rm_h_ipi(vcpu, server, mfrr);
+- if (unlikely(!__xive_vm_h_ipi))
+- return H_NOT_AVAILABLE;
+- return __xive_vm_h_ipi(vcpu, server, mfrr);
+- } else
++ if (xics_on_xive())
++ return xive_rm_h_ipi(vcpu, server, mfrr);
++ else
+ return xics_rm_h_ipi(vcpu, server, mfrr);
+ }
+
+@@ -624,13 +581,9 @@ int kvmppc_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr)
+ {
+ if (!kvmppc_xics_enabled(vcpu))
+ return H_TOO_HARD;
+- if (xics_on_xive()) {
+- if (is_rm())
+- return xive_rm_h_cppr(vcpu, cppr);
+- if (unlikely(!__xive_vm_h_cppr))
+- return H_NOT_AVAILABLE;
+- return __xive_vm_h_cppr(vcpu, cppr);
+- } else
++ if (xics_on_xive())
++ return xive_rm_h_cppr(vcpu, cppr);
++ else
+ return xics_rm_h_cppr(vcpu, cppr);
+ }
+
+@@ -638,13 +591,9 @@ int kvmppc_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr)
+ {
+ if (!kvmppc_xics_enabled(vcpu))
+ return H_TOO_HARD;
+- if (xics_on_xive()) {
+- if (is_rm())
+- return xive_rm_h_eoi(vcpu, xirr);
+- if (unlikely(!__xive_vm_h_eoi))
+- return H_NOT_AVAILABLE;
+- return __xive_vm_h_eoi(vcpu, xirr);
+- } else
++ if (xics_on_xive())
++ return xive_rm_h_eoi(vcpu, xirr);
++ else
+ return xics_rm_h_eoi(vcpu, xirr);
+ }
+ #endif /* CONFIG_KVM_XICS */
+diff --git a/arch/powerpc/kvm/book3s_hv_rmhandlers.S b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+index b1d9afffd841..274d62efa866 100644
+--- a/arch/powerpc/kvm/book3s_hv_rmhandlers.S
++++ b/arch/powerpc/kvm/book3s_hv_rmhandlers.S
+@@ -2535,7 +2535,7 @@ hcall_real_table:
+ #else
+ .long 0 /* 0x2fc - H_XIRR_X*/
+ #endif
+- .long DOTSYM(kvmppc_h_random) - hcall_real_table
++ .long DOTSYM(kvmppc_rm_h_random) - hcall_real_table
+ .globl hcall_real_table_end
+ hcall_real_table_end:
+
+diff --git a/arch/powerpc/kvm/book3s_xive.c b/arch/powerpc/kvm/book3s_xive.c
+index a0ebc29f30b2..8dfda8e01ac1 100644
+--- a/arch/powerpc/kvm/book3s_xive.c
++++ b/arch/powerpc/kvm/book3s_xive.c
+@@ -2245,21 +2245,3 @@ struct kvm_device_ops kvm_xive_ops = {
+ .get_attr = xive_get_attr,
+ .has_attr = xive_has_attr,
+ };
+-
+-void kvmppc_xive_init_module(void)
+-{
+- __xive_vm_h_xirr = xive_vm_h_xirr;
+- __xive_vm_h_ipoll = xive_vm_h_ipoll;
+- __xive_vm_h_ipi = xive_vm_h_ipi;
+- __xive_vm_h_cppr = xive_vm_h_cppr;
+- __xive_vm_h_eoi = xive_vm_h_eoi;
+-}
+-
+-void kvmppc_xive_exit_module(void)
+-{
+- __xive_vm_h_xirr = NULL;
+- __xive_vm_h_ipoll = NULL;
+- __xive_vm_h_ipi = NULL;
+- __xive_vm_h_cppr = NULL;
+- __xive_vm_h_eoi = NULL;
+-}
+diff --git a/arch/powerpc/kvm/book3s_xive.h b/arch/powerpc/kvm/book3s_xive.h
+index 382e3a56e789..8504389b130e 100644
+--- a/arch/powerpc/kvm/book3s_xive.h
++++ b/arch/powerpc/kvm/book3s_xive.h
+@@ -278,13 +278,6 @@ extern int xive_rm_h_ipi(struct kvm_vcpu *vcpu, unsigned long server,
+ extern int xive_rm_h_cppr(struct kvm_vcpu *vcpu, unsigned long cppr);
+ extern int xive_rm_h_eoi(struct kvm_vcpu *vcpu, unsigned long xirr);
+
+-extern unsigned long (*__xive_vm_h_xirr)(struct kvm_vcpu *vcpu);
+-extern unsigned long (*__xive_vm_h_ipoll)(struct kvm_vcpu *vcpu, unsigned long server);
+-extern int (*__xive_vm_h_ipi)(struct kvm_vcpu *vcpu, unsigned long server,
+- unsigned long mfrr);
+-extern int (*__xive_vm_h_cppr)(struct kvm_vcpu *vcpu, unsigned long cppr);
+-extern int (*__xive_vm_h_eoi)(struct kvm_vcpu *vcpu, unsigned long xirr);
+-
+ /*
+ * Common Xive routines for XICS-over-XIVE and XIVE native
+ */
+diff --git a/arch/powerpc/kvm/book3s_xive_native.c b/arch/powerpc/kvm/book3s_xive_native.c
+index a59a94f02733..4b00d4efb709 100644
+--- a/arch/powerpc/kvm/book3s_xive_native.c
++++ b/arch/powerpc/kvm/book3s_xive_native.c
+@@ -1271,13 +1271,3 @@ struct kvm_device_ops kvm_xive_native_ops = {
+ .has_attr = kvmppc_xive_native_has_attr,
+ .mmap = kvmppc_xive_native_mmap,
+ };
+-
+-void kvmppc_xive_native_init_module(void)
+-{
+- ;
+-}
+-
+-void kvmppc_xive_native_exit_module(void)
+-{
+- ;
+-}
+--
+2.35.1
+
--- /dev/null
+From 3ab0d29fb5f6584612a84c441dcbc2eb184836b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 21 May 2022 08:15:11 +0000
+Subject: KVM: set_msr_mce: Permit guests to ignore single-bit ECC errors
+
+From: Lev Kujawski <lkujaw@member.fsf.org>
+
+[ Upstream commit 0471a7bd1bca2a47a5f378f2222c5cf39ce94152 ]
+
+Certain guest operating systems (e.g., UNIXWARE) clear bit 0 of
+MC1_CTL to ignore single-bit ECC data errors. Single-bit ECC data
+errors are always correctable and thus are safe to ignore because they
+are informational in nature rather than signaling a loss of data
+integrity.
+
+Prior to this patch, these guests would crash upon writing MC1_CTL,
+with resultant error messages like the following:
+
+error: kvm run failed Operation not permitted
+EAX=fffffffe EBX=fffffffe ECX=00000404 EDX=ffffffff
+ESI=ffffffff EDI=00000001 EBP=fffdaba4 ESP=fffdab20
+EIP=c01333a5 EFL=00000246 [---Z-P-] CPL=0 II=0 A20=1 SMM=0 HLT=0
+ES =0108 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
+CS =0100 00000000 ffffffff 00c09b00 DPL=0 CS32 [-RA]
+SS =0108 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
+DS =0108 00000000 ffffffff 00c09300 DPL=0 DS [-WA]
+FS =0000 00000000 ffffffff 00c00000
+GS =0000 00000000 ffffffff 00c00000
+LDT=0118 c1026390 00000047 00008200 DPL=0 LDT
+TR =0110 ffff5af0 00000067 00008b00 DPL=0 TSS32-busy
+GDT= ffff5020 000002cf
+IDT= ffff52f0 000007ff
+CR0=8001003b CR2=00000000 CR3=0100a000 CR4=00000230
+DR0=00000000 DR1=00000000 DR2=00000000 DR3=00000000
+DR6=ffff0ff0 DR7=00000400
+EFER=0000000000000000
+Code=08 89 01 89 51 04 c3 8b 4c 24 08 8b 01 8b 51 04 8b 4c 24 04 <0f>
+30 c3 f7 05 a4 6d ff ff 10 00 00 00 74 03 0f 31 c3 33 c0 33 d2 c3 8d
+74 26 00 0f 31 c3
+
+Signed-off-by: Lev Kujawski <lkujaw@member.fsf.org>
+Message-Id: <20220521081511.187388-1-lkujaw@member.fsf.org>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 29a8ca95c581..23a5e5880615 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -2862,10 +2862,13 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ /* 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
+- * this to avoid an uncatched #GP in the guest
++ * this to avoid an uncatched #GP in the guest.
++ *
++ * UNIXWARE clears bit 0 of MC1_CTL to ignore
++ * correctable, single-bit ECC data errors.
+ */
+ if ((offset & 0x3) == 0 &&
+- data != 0 && (data | (1 << 10)) != ~(u64)0)
++ data != 0 && (data | (1 << 10) | 1) != ~(u64)0)
+ return -1;
+
+ /* MCi_STATUS */
+--
+2.35.1
+
--- /dev/null
+From 7dd5a543bcc294e4d7be649f82f8acf1dda89a18 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Oct 2020 18:44:14 -0700
+Subject: KVM: SVM: Drop VMXE check from svm_set_cr4()
+
+From: Sean Christopherson <sean.j.christopherson@intel.com>
+
+[ Upstream commit 311a06593b9a3944a63ed176b95cb8d857f7c83b ]
+
+Drop svm_set_cr4()'s explicit check CR4.VMXE now that common x86 handles
+the check by incorporating VMXE into the CR4 reserved bits, via
+kvm_cpu_caps. SVM obviously does not set X86_FEATURE_VMX.
+
+No functional change intended.
+
+Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
+Message-Id: <20201007014417.29276-4-sean.j.christopherson@intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/svm/svm.c | 3 ---
+ 1 file changed, 3 deletions(-)
+
+diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
+index 184e68e7eedf..9bc166a5d453 100644
+--- a/arch/x86/kvm/svm/svm.c
++++ b/arch/x86/kvm/svm/svm.c
+@@ -1697,9 +1697,6 @@ int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ unsigned long host_cr4_mce = cr4_read_shadow() & X86_CR4_MCE;
+ unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4;
+
+- if (cr4 & X86_CR4_VMXE)
+- return 1;
+-
+ if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE))
+ svm_flush_tlb(vcpu);
+
+--
+2.35.1
+
--- /dev/null
+From ce4efc4739490eef5363b1266e3b68a0405670b7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Oct 2020 18:44:13 -0700
+Subject: KVM: VMX: Drop explicit 'nested' check from vmx_set_cr4()
+
+From: Sean Christopherson <sean.j.christopherson@intel.com>
+
+[ Upstream commit a447e38a7fadb2e554c3942dda183e55cccd5df0 ]
+
+Drop vmx_set_cr4()'s explicit check on the 'nested' module param now
+that common x86 handles the check by incorporating VMXE into the CR4
+reserved bits, via kvm_cpu_caps. X86_FEATURE_VMX is set in kvm_cpu_caps
+(by vmx_set_cpu_caps()), if and only if 'nested' is true.
+
+No functional change intended.
+
+Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
+Message-Id: <20201007014417.29276-3-sean.j.christopherson@intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/vmx.c | 19 +++++++------------
+ 1 file changed, 7 insertions(+), 12 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
+index 1b75847d8a49..154ec5d8cdf5 100644
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -3211,18 +3211,13 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ }
+ }
+
+- if (cr4 & X86_CR4_VMXE) {
+- /*
+- * To use VMXON (and later other VMX instructions), a guest
+- * must first be able to turn on cr4.VMXE (see handle_vmon()).
+- * So basically the check on whether to allow nested VMX
+- * is here. We operate under the default treatment of SMM,
+- * so VMX cannot be enabled under SMM. Note, guest CPUID is
+- * intentionally ignored, it's handled by cr4_guest_rsvd_bits.
+- */
+- if (!nested || is_smm(vcpu))
+- return 1;
+- }
++ /*
++ * We operate under the default treatment of SMM, so VMX cannot be
++ * enabled under SMM. Note, whether or not VMXE is allowed at all is
++ * handled by kvm_valid_cr4().
++ */
++ if ((cr4 & X86_CR4_VMXE) && is_smm(vcpu))
++ return 1;
+
+ if (vmx->nested.vmxon && !nested_cr4_valid(vcpu, cr4))
+ return 1;
+--
+2.35.1
+
--- /dev/null
+From cd8244785a8b7d8f6440b7ddff0a495d17f9fc1d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Oct 2020 18:44:12 -0700
+Subject: KVM: VMX: Drop guest CPUID check for VMXE in vmx_set_cr4()
+
+From: Sean Christopherson <sean.j.christopherson@intel.com>
+
+[ Upstream commit d3a9e4146a6f79f19430bca3f2a4d6ebaaffe36b ]
+
+Drop vmx_set_cr4()'s somewhat hidden guest_cpuid_has() check on VMXE now
+that common x86 handles the check by incorporating VMXE into the CR4
+reserved bits, i.e. in cr4_guest_rsvd_bits. This fixes a bug where KVM
+incorrectly rejects KVM_SET_SREGS with CR4.VMXE=1 if it's executed
+before KVM_SET_CPUID{,2}.
+
+Fixes: 5e1746d6205d ("KVM: nVMX: Allow setting the VMXE bit in CR4")
+Reported-by: Stas Sergeev <stsp@users.sourceforge.net>
+Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
+Message-Id: <20201007014417.29276-2-sean.j.christopherson@intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/vmx.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
+index 9b520da3f748..1b75847d8a49 100644
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -3217,9 +3217,10 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ * must first be able to turn on cr4.VMXE (see handle_vmon()).
+ * So basically the check on whether to allow nested VMX
+ * is here. We operate under the default treatment of SMM,
+- * so VMX cannot be enabled under SMM.
++ * so VMX cannot be enabled under SMM. Note, guest CPUID is
++ * intentionally ignored, it's handled by cr4_guest_rsvd_bits.
+ */
+- if (!nested_vmx_allowed(vcpu) || is_smm(vcpu))
++ if (!nested || is_smm(vcpu))
+ return 1;
+ }
+
+--
+2.35.1
+
--- /dev/null
+From f20bfd979567637f1241cfdd05fc51b6a39a5d36 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Jul 2022 22:44:06 +0000
+Subject: KVM: VMX: Mark all PERF_GLOBAL_(OVF)_CTRL bits reserved if there's no
+ vPMU
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 93255bf92939d948bc86d81c6bb70bb0fecc5db1 ]
+
+Mark all MSR_CORE_PERF_GLOBAL_CTRL and MSR_CORE_PERF_GLOBAL_OVF_CTRL bits
+as reserved if there is no guest vPMU. The nVMX VM-Entry consistency
+checks do not check for a valid vPMU prior to consuming the masks via
+kvm_valid_perf_global_ctrl(), i.e. may incorrectly allow a non-zero mask
+to be loaded via VM-Enter or VM-Exit (well, attempted to be loaded, the
+actual MSR load will be rejected by intel_is_valid_msr()).
+
+Fixes: f5132b01386b ("KVM: Expose a version 2 architectural PMU to a guests")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Message-Id: <20220722224409.1336532-3-seanjc@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/pmu_intel.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index ea5a7056fdfd..e73378b6f10c 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -335,6 +335,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ pmu->version = 0;
+ pmu->reserved_bits = 0xffffffff00200000ull;
+ pmu->raw_event_mask = X86_RAW_EVENT_MASK;
++ pmu->global_ctrl_mask = ~0ull;
++ pmu->global_ovf_ctrl_mask = ~0ull;
+ pmu->fixed_ctr_ctrl_mask = ~0ull;
+
+ entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
+--
+2.35.1
+
--- /dev/null
+From 9ff8ea8acf44ef88e89a4987ce47e327f79be0df Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 6 Oct 2020 18:44:15 -0700
+Subject: KVM: x86: Move vendor CR4 validity check to dedicated kvm_x86_ops
+ hook
+
+From: Sean Christopherson <sean.j.christopherson@intel.com>
+
+[ Upstream commit c2fe3cd4604ac87c587db05d41843d667dc43815 ]
+
+Split out VMX's checks on CR4.VMXE to a dedicated hook, .is_valid_cr4(),
+and invoke the new hook from kvm_valid_cr4(). This fixes an issue where
+KVM_SET_SREGS would return success while failing to actually set CR4.
+
+Fixing the issue by explicitly checking kvm_x86_ops.set_cr4()'s return
+in __set_sregs() is not a viable option as KVM has already stuffed a
+variety of vCPU state.
+
+Note, kvm_valid_cr4() and is_valid_cr4() have different return types and
+inverted semantics. This will be remedied in a future patch.
+
+Fixes: 5e1746d6205d ("KVM: nVMX: Allow setting the VMXE bit in CR4")
+Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
+Message-Id: <20201007014417.29276-5-sean.j.christopherson@intel.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/kvm_host.h | 3 ++-
+ arch/x86/kvm/svm/svm.c | 9 +++++++--
+ arch/x86/kvm/svm/svm.h | 2 +-
+ arch/x86/kvm/vmx/nested.c | 2 +-
+ arch/x86/kvm/vmx/vmx.c | 31 ++++++++++++++++++-------------
+ arch/x86/kvm/vmx/vmx.h | 2 +-
+ arch/x86/kvm/x86.c | 6 ++++--
+ 7 files changed, 34 insertions(+), 21 deletions(-)
+
+diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
+index 94fbbdb888cf..87c13ef4ee8e 100644
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -1117,7 +1117,8 @@ struct kvm_x86_ops {
+ struct kvm_segment *var, int seg);
+ void (*get_cs_db_l_bits)(struct kvm_vcpu *vcpu, int *db, int *l);
+ void (*set_cr0)(struct kvm_vcpu *vcpu, unsigned long cr0);
+- int (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
++ bool (*is_valid_cr4)(struct kvm_vcpu *vcpu, unsigned long cr0);
++ void (*set_cr4)(struct kvm_vcpu *vcpu, unsigned long cr4);
+ int (*set_efer)(struct kvm_vcpu *vcpu, u64 efer);
+ void (*get_idt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
+ void (*set_idt)(struct kvm_vcpu *vcpu, struct desc_ptr *dt);
+diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
+index 9bc166a5d453..442705517caf 100644
+--- a/arch/x86/kvm/svm/svm.c
++++ b/arch/x86/kvm/svm/svm.c
+@@ -1692,7 +1692,12 @@ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0)
+ update_cr0_intercept(svm);
+ }
+
+-int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
++static bool svm_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
++{
++ return true;
++}
++
++void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ {
+ unsigned long host_cr4_mce = cr4_read_shadow() & X86_CR4_MCE;
+ unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4;
+@@ -1706,7 +1711,6 @@ int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ cr4 |= host_cr4_mce;
+ to_svm(vcpu)->vmcb->save.cr4 = cr4;
+ vmcb_mark_dirty(to_svm(vcpu)->vmcb, VMCB_CR);
+- return 0;
+ }
+
+ static void svm_set_segment(struct kvm_vcpu *vcpu,
+@@ -4238,6 +4242,7 @@ static struct kvm_x86_ops svm_x86_ops __initdata = {
+ .get_cpl = svm_get_cpl,
+ .get_cs_db_l_bits = kvm_get_cs_db_l_bits,
+ .set_cr0 = svm_set_cr0,
++ .is_valid_cr4 = svm_is_valid_cr4,
+ .set_cr4 = svm_set_cr4,
+ .set_efer = svm_set_efer,
+ .get_idt = svm_get_idt,
+diff --git a/arch/x86/kvm/svm/svm.h b/arch/x86/kvm/svm/svm.h
+index 2c007241fbf5..10aba1dd264e 100644
+--- a/arch/x86/kvm/svm/svm.h
++++ b/arch/x86/kvm/svm/svm.h
+@@ -355,7 +355,7 @@ void svm_vcpu_free_msrpm(u32 *msrpm);
+
+ int svm_set_efer(struct kvm_vcpu *vcpu, u64 efer);
+ void svm_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
+-int svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
++void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
+ void svm_flush_tlb(struct kvm_vcpu *vcpu);
+ void disable_nmi_singlestep(struct vcpu_svm *svm);
+ bool svm_smi_blocked(struct kvm_vcpu *vcpu);
+diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
+index c4e37d81b158..3228db4db5df 100644
+--- a/arch/x86/kvm/vmx/nested.c
++++ b/arch/x86/kvm/vmx/nested.c
+@@ -4879,7 +4879,7 @@ static int handle_vmon(struct kvm_vcpu *vcpu)
+ /*
+ * The Intel VMX Instruction Reference lists a bunch of bits that are
+ * prerequisite to running VMXON, most notably cr4.VMXE must be set to
+- * 1 (see vmx_set_cr4() for when we allow the guest to set this).
++ * 1 (see vmx_is_valid_cr4() for when we allow the guest to set this).
+ * Otherwise, we should fail with #UD. But most faulting conditions
+ * have already been checked by hardware, prior to the VM-exit for
+ * VMXON. We do test guest cr4.VMXE because processor CR4 always has
+diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
+index 154ec5d8cdf5..b33d0f283d4f 100644
+--- a/arch/x86/kvm/vmx/vmx.c
++++ b/arch/x86/kvm/vmx/vmx.c
+@@ -3183,7 +3183,23 @@ static void vmx_load_mmu_pgd(struct kvm_vcpu *vcpu, unsigned long pgd,
+ vmcs_writel(GUEST_CR3, guest_cr3);
+ }
+
+-int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
++static bool vmx_is_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
++{
++ /*
++ * We operate under the default treatment of SMM, so VMX cannot be
++ * enabled under SMM. Note, whether or not VMXE is allowed at all is
++ * handled by kvm_valid_cr4().
++ */
++ if ((cr4 & X86_CR4_VMXE) && is_smm(vcpu))
++ return false;
++
++ if (to_vmx(vcpu)->nested.vmxon && !nested_cr4_valid(vcpu, cr4))
++ return false;
++
++ return true;
++}
++
++void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ {
+ struct vcpu_vmx *vmx = to_vmx(vcpu);
+ /*
+@@ -3211,17 +3227,6 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ }
+ }
+
+- /*
+- * We operate under the default treatment of SMM, so VMX cannot be
+- * enabled under SMM. Note, whether or not VMXE is allowed at all is
+- * handled by kvm_valid_cr4().
+- */
+- if ((cr4 & X86_CR4_VMXE) && is_smm(vcpu))
+- return 1;
+-
+- if (vmx->nested.vmxon && !nested_cr4_valid(vcpu, cr4))
+- return 1;
+-
+ vcpu->arch.cr4 = cr4;
+ kvm_register_mark_available(vcpu, VCPU_EXREG_CR4);
+
+@@ -3252,7 +3257,6 @@ int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+
+ vmcs_writel(CR4_READ_SHADOW, cr4);
+ vmcs_writel(GUEST_CR4, hw_cr4);
+- return 0;
+ }
+
+ void vmx_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg)
+@@ -7748,6 +7752,7 @@ static struct kvm_x86_ops vmx_x86_ops __initdata = {
+ .get_cpl = vmx_get_cpl,
+ .get_cs_db_l_bits = vmx_get_cs_db_l_bits,
+ .set_cr0 = vmx_set_cr0,
++ .is_valid_cr4 = vmx_is_valid_cr4,
+ .set_cr4 = vmx_set_cr4,
+ .set_efer = vmx_set_efer,
+ .get_idt = vmx_get_idt,
+diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
+index a6b52d3a39c9..24903f05c204 100644
+--- a/arch/x86/kvm/vmx/vmx.h
++++ b/arch/x86/kvm/vmx/vmx.h
+@@ -347,7 +347,7 @@ u32 vmx_get_interrupt_shadow(struct kvm_vcpu *vcpu);
+ void vmx_set_interrupt_shadow(struct kvm_vcpu *vcpu, int mask);
+ int vmx_set_efer(struct kvm_vcpu *vcpu, u64 efer);
+ void vmx_set_cr0(struct kvm_vcpu *vcpu, unsigned long cr0);
+-int vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
++void vmx_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4);
+ void set_cr4_guest_host_mask(struct vcpu_vmx *vmx);
+ void ept_save_pdptrs(struct kvm_vcpu *vcpu);
+ void vmx_get_segment(struct kvm_vcpu *vcpu, struct kvm_segment *var, int seg);
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 98422a53bb1e..5f4f855bb3b1 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -986,6 +986,9 @@ int kvm_valid_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ if (cr4 & vcpu->arch.cr4_guest_rsvd_bits)
+ return -EINVAL;
+
++ if (!kvm_x86_ops.is_valid_cr4(vcpu, cr4))
++ return -EINVAL;
++
+ return 0;
+ }
+ EXPORT_SYMBOL_GPL(kvm_valid_cr4);
+@@ -1020,8 +1023,7 @@ int kvm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
+ return 1;
+ }
+
+- if (kvm_x86_ops.set_cr4(vcpu, cr4))
+- return 1;
++ kvm_x86_ops.set_cr4(vcpu, cr4);
+
+ if (((cr4 ^ old_cr4) & mmu_role_bits) ||
+ (!(cr4 & X86_CR4_PCIDE) && (old_cr4 & X86_CR4_PCIDE)))
+--
+2.35.1
+
--- /dev/null
+From 3506aff200bd63a96e7cfd97a3fa644a1f0df37e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 18:22:02 +0800
+Subject: KVM: x86/pmu: Ignore pmu->global_ctrl check if vPMU doesn't support
+ global_ctrl
+
+From: Like Xu <likexu@tencent.com>
+
+[ Upstream commit 98defd2e17803263f49548fea930cfc974d505aa ]
+
+MSR_CORE_PERF_GLOBAL_CTRL is introduced as part of Architecture PMU V2,
+as indicated by Intel SDM 19.2.2 and the intel_is_valid_msr() function.
+
+So in the absence of global_ctrl support, all PMCs are enabled as AMD does.
+
+Signed-off-by: Like Xu <likexu@tencent.com>
+Message-Id: <20220509102204.62389-1-likexu@tencent.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/pmu_intel.c | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index e73378b6f10c..f938fc997766 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -104,6 +104,9 @@ static bool intel_pmc_is_enabled(struct kvm_pmc *pmc)
+ {
+ struct kvm_pmu *pmu = pmc_to_pmu(pmc);
+
++ if (pmu->version < 2)
++ return true;
++
+ return test_bit(pmc->idx, (unsigned long *)&pmu->global_ctrl);
+ }
+
+--
+2.35.1
+
--- /dev/null
+From 580cc36fd844a6c7cff1a868d55f6be0465059ef Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 11 Apr 2022 18:19:34 +0800
+Subject: KVM: x86/pmu: Introduce the ctrl_mask value for fixed counter
+
+From: Like Xu <like.xu@linux.intel.com>
+
+[ Upstream commit 2c985527dd8d283e786ad7a67e532ef7f6f00fac ]
+
+The mask value of fixed counter control register should be dynamic
+adjusted with the number of fixed counters. This patch introduces a
+variable that includes the reserved bits of fixed counter control
+registers. This is a generic code refactoring.
+
+Co-developed-by: Luwei Kang <luwei.kang@intel.com>
+Signed-off-by: Luwei Kang <luwei.kang@intel.com>
+Signed-off-by: Like Xu <like.xu@linux.intel.com>
+Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
+Message-Id: <20220411101946.20262-6-likexu@tencent.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/kvm_host.h | 1 +
+ arch/x86/kvm/vmx/pmu_intel.c | 6 +++++-
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
+index 613334d626b2..38c63a78aba6 100644
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -432,6 +432,7 @@ struct kvm_pmu {
+ unsigned nr_arch_fixed_counters;
+ unsigned available_event_types;
+ u64 fixed_ctr_ctrl;
++ u64 fixed_ctr_ctrl_mask;
+ u64 global_ctrl;
+ u64 global_status;
+ u64 global_ovf_ctrl;
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index 663b6eb5de66..ea5a7056fdfd 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -259,7 +259,7 @@ static int intel_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ case MSR_CORE_PERF_FIXED_CTR_CTRL:
+ if (pmu->fixed_ctr_ctrl == data)
+ return 0;
+- if (!(data & 0xfffffffffffff444ull)) {
++ if (!(data & pmu->fixed_ctr_ctrl_mask)) {
+ reprogram_fixed_counters(pmu, data);
+ return 0;
+ }
+@@ -326,6 +326,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ struct kvm_cpuid_entry2 *entry;
+ union cpuid10_eax eax;
+ union cpuid10_edx edx;
++ int i;
+
+ pmu->nr_arch_gp_counters = 0;
+ pmu->nr_arch_fixed_counters = 0;
+@@ -334,6 +335,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ pmu->version = 0;
+ pmu->reserved_bits = 0xffffffff00200000ull;
+ pmu->raw_event_mask = X86_RAW_EVENT_MASK;
++ pmu->fixed_ctr_ctrl_mask = ~0ull;
+
+ entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
+ if (!entry)
+@@ -367,6 +369,8 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ ((u64)1 << edx.split.bit_width_fixed) - 1;
+ }
+
++ for (i = 0; i < pmu->nr_arch_fixed_counters; i++)
++ pmu->fixed_ctr_ctrl_mask &= ~(0xbull << (i * 4));
+ pmu->global_ctrl = ((1ull << pmu->nr_arch_gp_counters) - 1) |
+ (((1ull << pmu->nr_arch_fixed_counters) - 1) << INTEL_PMC_IDX_FIXED);
+ pmu->global_ctrl_mask = ~pmu->global_ctrl;
+--
+2.35.1
+
--- /dev/null
+From 0d14144e398fae91e6b0de7c7baa213776e5dc72 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 2 Feb 2021 09:32:35 -0500
+Subject: KVM: x86/pmu: preserve IA32_PERF_CAPABILITIES across CPUID refresh
+
+From: Paolo Bonzini <pbonzini@redhat.com>
+
+[ Upstream commit a755753903a40d982f6dd23d65eb96b248a2577a ]
+
+Once MSR_IA32_PERF_CAPABILITIES is changed via vmx_set_msr(), the
+value should not be changed by cpuid(). To ensure that the new value
+is kept, the default initialization path is moved to intel_pmu_init().
+The effective value of the MSR will be 0 if PDCM is clear, however.
+
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/vmx/pmu_intel.c | 16 ++++++++++------
+ 1 file changed, 10 insertions(+), 6 deletions(-)
+
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index bd70c1d7f345..b3ca19682975 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -153,12 +153,17 @@ static struct kvm_pmc *intel_rdpmc_ecx_to_pmc(struct kvm_vcpu *vcpu,
+ return &counters[array_index_nospec(idx, num_counters)];
+ }
+
+-static inline bool fw_writes_is_enabled(struct kvm_vcpu *vcpu)
++static inline u64 vcpu_get_perf_capabilities(struct kvm_vcpu *vcpu)
+ {
+ if (!guest_cpuid_has(vcpu, X86_FEATURE_PDCM))
+- return false;
++ return 0;
+
+- return vcpu->arch.perf_capabilities & PMU_CAP_FW_WRITES;
++ return vcpu->arch.perf_capabilities;
++}
++
++static inline bool fw_writes_is_enabled(struct kvm_vcpu *vcpu)
++{
++ return (vcpu_get_perf_capabilities(vcpu) & PMU_CAP_FW_WRITES) != 0;
+ }
+
+ static inline struct kvm_pmc *get_fw_gp_pmc(struct kvm_pmu *pmu, u32 msr)
+@@ -328,7 +333,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
+ pmu->version = 0;
+ pmu->reserved_bits = 0xffffffff00200000ull;
+- vcpu->arch.perf_capabilities = 0;
+
+ entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
+ if (!entry)
+@@ -341,8 +345,6 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ return;
+
+ perf_get_x86_pmu_capability(&x86_pmu);
+- if (guest_cpuid_has(vcpu, X86_FEATURE_PDCM))
+- vcpu->arch.perf_capabilities = vmx_get_perf_capabilities();
+
+ pmu->nr_arch_gp_counters = min_t(int, eax.split.num_counters,
+ x86_pmu.num_counters_gp);
+@@ -406,6 +408,8 @@ static void intel_pmu_init(struct kvm_vcpu *vcpu)
+ pmu->fixed_counters[i].idx = i + INTEL_PMC_IDX_FIXED;
+ pmu->fixed_counters[i].current_config = 0;
+ }
++
++ vcpu->arch.perf_capabilities = vmx_get_perf_capabilities();
+ }
+
+ static void intel_pmu_reset(struct kvm_vcpu *vcpu)
+--
+2.35.1
+
--- /dev/null
+From 8fa9b402675940ffdc830d8be113758354f6e722 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 14 Jan 2022 21:24:26 -0800
+Subject: KVM: x86/pmu: Use binary search to check filtered events
+
+From: Jim Mattson <jmattson@google.com>
+
+[ Upstream commit 7ff775aca48adc854436b92c060e5eebfffb6a4a ]
+
+The PMU event filter may contain up to 300 events. Replace the linear
+search in reprogram_gp_counter() with a binary search.
+
+Signed-off-by: Jim Mattson <jmattson@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Message-Id: <20220115052431.447232-2-jmattson@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/pmu.c | 30 +++++++++++++++++++-----------
+ 1 file changed, 19 insertions(+), 11 deletions(-)
+
+diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
+index 2f83b5d948b3..350e7cdaad02 100644
+--- a/arch/x86/kvm/pmu.c
++++ b/arch/x86/kvm/pmu.c
+@@ -13,6 +13,8 @@
+ #include <linux/types.h>
+ #include <linux/kvm_host.h>
+ #include <linux/perf_event.h>
++#include <linux/bsearch.h>
++#include <linux/sort.h>
+ #include <asm/perf_event.h>
+ #include "x86.h"
+ #include "cpuid.h"
+@@ -168,13 +170,17 @@ static bool pmc_resume_counter(struct kvm_pmc *pmc)
+ return true;
+ }
+
++static int cmp_u64(const void *a, const void *b)
++{
++ return *(__u64 *)a - *(__u64 *)b;
++}
++
+ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
+ {
+ u64 config;
+ u32 type = PERF_TYPE_RAW;
+ struct kvm *kvm = pmc->vcpu->kvm;
+ struct kvm_pmu_event_filter *filter;
+- int i;
+ bool allow_event = true;
+
+ if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
+@@ -189,16 +195,13 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
+
+ filter = srcu_dereference(kvm->arch.pmu_event_filter, &kvm->srcu);
+ if (filter) {
+- for (i = 0; i < filter->nevents; i++)
+- if (filter->events[i] ==
+- (eventsel & AMD64_RAW_EVENT_MASK_NB))
+- break;
+- if (filter->action == KVM_PMU_EVENT_ALLOW &&
+- i == filter->nevents)
+- allow_event = false;
+- if (filter->action == KVM_PMU_EVENT_DENY &&
+- i < filter->nevents)
+- allow_event = false;
++ __u64 key = eventsel & AMD64_RAW_EVENT_MASK_NB;
++
++ if (bsearch(&key, filter->events, filter->nevents,
++ sizeof(__u64), cmp_u64))
++ allow_event = filter->action == KVM_PMU_EVENT_ALLOW;
++ else
++ allow_event = filter->action == KVM_PMU_EVENT_DENY;
+ }
+ if (!allow_event)
+ return;
+@@ -507,6 +510,11 @@ int kvm_vm_ioctl_set_pmu_event_filter(struct kvm *kvm, void __user *argp)
+ /* Ensure nevents can't be changed between the user copies. */
+ *filter = tmp;
+
++ /*
++ * Sort the in-kernel list so that we can search it with bsearch.
++ */
++ sort(&filter->events, filter->nevents, sizeof(__u64), cmp_u64, NULL);
++
+ mutex_lock(&kvm->lock);
+ filter = rcu_replace_pointer(kvm->arch.pmu_event_filter, filter,
+ mutex_is_locked(&kvm->lock));
+--
+2.35.1
+
--- /dev/null
+From 093b917d33a2fc3be375cc71406a27d376347204 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 7 Mar 2022 17:24:52 -0800
+Subject: KVM: x86/pmu: Use different raw event masks for AMD and Intel
+
+From: Jim Mattson <jmattson@google.com>
+
+[ Upstream commit 95b065bf5c431c06c68056a03a5853b660640ecc ]
+
+The third nybble of AMD's event select overlaps with Intel's IN_TX and
+IN_TXCP bits. Therefore, we can't use AMD64_RAW_EVENT_MASK on Intel
+platforms that support TSX.
+
+Declare a raw_event_mask in the kvm_pmu structure, initialize it in
+the vendor-specific pmu_refresh() functions, and use that mask for
+PERF_TYPE_RAW configurations in reprogram_gp_counter().
+
+Fixes: 710c47651431 ("KVM: x86/pmu: Use AMD64_RAW_EVENT_MASK for PERF_TYPE_RAW")
+Signed-off-by: Jim Mattson <jmattson@google.com>
+Message-Id: <20220308012452.3468611-1-jmattson@google.com>
+Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/include/asm/kvm_host.h | 1 +
+ arch/x86/kvm/pmu.c | 3 ++-
+ arch/x86/kvm/svm/pmu.c | 1 +
+ arch/x86/kvm/vmx/pmu_intel.c | 1 +
+ 4 files changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
+index 87c13ef4ee8e..613334d626b2 100644
+--- a/arch/x86/include/asm/kvm_host.h
++++ b/arch/x86/include/asm/kvm_host.h
+@@ -439,6 +439,7 @@ struct kvm_pmu {
+ u64 global_ctrl_mask;
+ u64 global_ovf_ctrl_mask;
+ u64 reserved_bits;
++ u64 raw_event_mask;
+ u8 version;
+ struct kvm_pmc gp_counters[INTEL_PMC_MAX_GENERIC];
+ struct kvm_pmc fixed_counters[INTEL_PMC_MAX_FIXED];
+diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
+index 350e7cdaad02..8b622ae9f2b4 100644
+--- a/arch/x86/kvm/pmu.c
++++ b/arch/x86/kvm/pmu.c
+@@ -181,6 +181,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
+ u32 type = PERF_TYPE_RAW;
+ struct kvm *kvm = pmc->vcpu->kvm;
+ struct kvm_pmu_event_filter *filter;
++ struct kvm_pmu *pmu = vcpu_to_pmu(pmc->vcpu);
+ bool allow_event = true;
+
+ if (eventsel & ARCH_PERFMON_EVENTSEL_PIN_CONTROL)
+@@ -217,7 +218,7 @@ void reprogram_gp_counter(struct kvm_pmc *pmc, u64 eventsel)
+ }
+
+ if (type == PERF_TYPE_RAW)
+- config = eventsel & AMD64_RAW_EVENT_MASK;
++ config = eventsel & pmu->raw_event_mask;
+
+ if (pmc->current_config == eventsel && pmc_resume_counter(pmc))
+ return;
+diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c
+index 49e5be735f14..35da84f63b20 100644
+--- a/arch/x86/kvm/svm/pmu.c
++++ b/arch/x86/kvm/svm/pmu.c
+@@ -295,6 +295,7 @@ static void amd_pmu_refresh(struct kvm_vcpu *vcpu)
+
+ pmu->counter_bitmask[KVM_PMC_GP] = ((u64)1 << 48) - 1;
+ pmu->reserved_bits = 0xfffffff000280000ull;
++ pmu->raw_event_mask = AMD64_RAW_EVENT_MASK;
+ pmu->version = 1;
+ /* not applicable to AMD; but clean them to prevent any fall out */
+ pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
+diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
+index b3ca19682975..663b6eb5de66 100644
+--- a/arch/x86/kvm/vmx/pmu_intel.c
++++ b/arch/x86/kvm/vmx/pmu_intel.c
+@@ -333,6 +333,7 @@ static void intel_pmu_refresh(struct kvm_vcpu *vcpu)
+ pmu->counter_bitmask[KVM_PMC_FIXED] = 0;
+ pmu->version = 0;
+ pmu->reserved_bits = 0xffffffff00200000ull;
++ pmu->raw_event_mask = X86_RAW_EVENT_MASK;
+
+ entry = kvm_find_cpuid_entry(vcpu, 0xa, 0);
+ if (!entry)
+--
+2.35.1
+
--- /dev/null
+From 93d821666b20f473bce1e34edb8cdf904f049422 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 May 2022 22:27:14 +0000
+Subject: KVM: x86: Signal #GP, not -EPERM, on bad WRMSR(MCi_CTL/STATUS)
+
+From: Sean Christopherson <seanjc@google.com>
+
+[ Upstream commit 2368048bf5c2ec4b604ac3431564071e89a0bc71 ]
+
+Return '1', not '-1', when handling an illegal WRMSR to a MCi_CTL or
+MCi_STATUS MSR. The behavior of "all zeros' or "all ones" for CTL MSRs
+is architectural, as is the "only zeros" behavior for STATUS MSRs. I.e.
+the intent is to inject a #GP, not exit to userspace due to an unhandled
+emulation case. Returning '-1' gets interpreted as -EPERM up the stack
+and effecitvely kills the guest.
+
+Fixes: 890ca9aefa78 ("KVM: Add MCE support")
+Fixes: 9ffd986c6e4e ("KVM: X86: #GP when guest attempts to write MCi_STATUS register w/o 0")
+Cc: stable@vger.kernel.org
+Signed-off-by: Sean Christopherson <seanjc@google.com>
+Reviewed-by: Jim Mattson <jmattson@google.com>
+Link: https://lore.kernel.org/r/20220512222716.4112548-2-seanjc@google.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/kvm/x86.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
+index 23a5e5880615..98422a53bb1e 100644
+--- a/arch/x86/kvm/x86.c
++++ b/arch/x86/kvm/x86.c
+@@ -2869,13 +2869,13 @@ static int set_msr_mce(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+ */
+ if ((offset & 0x3) == 0 &&
+ data != 0 && (data | (1 << 10) | 1) != ~(u64)0)
+- return -1;
++ return 1;
+
+ /* MCi_STATUS */
+ if (!msr_info->host_initiated &&
+ (offset & 0x3) == 1 && data != 0) {
+ if (!can_set_mci_status(vcpu))
+- return -1;
++ return 1;
+ }
+
+ vcpu->arch.mce_banks[offset] = data;
+--
+2.35.1
+
--- /dev/null
+From 89f4b362ea123bbd62302cfd30ebb343fbebb2da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 May 2021 23:37:29 +0200
+Subject: mtd: rawnand: Add a helper to clarify the interface configuration
+
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+
+[ Upstream commit 961965c45c706175b24227868b1c12d72775e446 ]
+
+Name it nand_interface_is_sdr() which will make even more sense when
+nand_interface_is_nvddr() will be introduced.
+
+Use it when relevant.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20210505213750.257417-2-miquel.raynal@bootlin.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/nand/raw/atmel/nand-controller.c | 2 +-
+ include/linux/mtd/rawnand.h | 11 ++++++++++-
+ 2 files changed, 11 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/mtd/nand/raw/atmel/nand-controller.c b/drivers/mtd/nand/raw/atmel/nand-controller.c
+index c048e826746a..2228c34f3dea 100644
+--- a/drivers/mtd/nand/raw/atmel/nand-controller.c
++++ b/drivers/mtd/nand/raw/atmel/nand-controller.c
+@@ -1246,7 +1246,7 @@ static int atmel_smc_nand_prepare_smcconf(struct atmel_nand *nand,
+ nc = to_nand_controller(nand->base.controller);
+
+ /* DDR interface not supported. */
+- if (conf->type != NAND_SDR_IFACE)
++ if (!nand_interface_is_sdr(conf))
+ return -ENOTSUPP;
+
+ /*
+diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
+index db2eaff77f41..75535036b126 100644
+--- a/include/linux/mtd/rawnand.h
++++ b/include/linux/mtd/rawnand.h
+@@ -499,6 +499,15 @@ struct nand_interface_config {
+ } timings;
+ };
+
++/**
++ * nand_interface_is_sdr - get the interface type
++ * @conf: The data interface
++ */
++static bool nand_interface_is_sdr(const struct nand_interface_config *conf)
++{
++ return conf->type == NAND_SDR_IFACE;
++}
++
+ /**
+ * nand_get_sdr_timings - get SDR timing from data interface
+ * @conf: The data interface
+@@ -506,7 +515,7 @@ struct nand_interface_config {
+ static inline const struct nand_sdr_timings *
+ nand_get_sdr_timings(const struct nand_interface_config *conf)
+ {
+- if (conf->type != NAND_SDR_IFACE)
++ if (!nand_interface_is_sdr(conf))
+ return ERR_PTR(-EINVAL);
+
+ return &conf->timings.sdr;
+--
+2.35.1
+
--- /dev/null
+From 98ef76f18b92d8bdc6c5fbf7813454f4a9f2e2a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 May 2021 23:37:36 +0200
+Subject: mtd: rawnand: Add NV-DDR timings
+
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+
+[ Upstream commit 1666b815ad1a5b6373e950da5002ac46521a9b28 ]
+
+Create the relevant ONFI NV-DDR timings structure and fill it with
+default values from the ONFI specification.
+
+Add the relevant structure entries and helpers.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20210505213750.257417-9-miquel.raynal@bootlin.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/nand/raw/nand_timings.c | 255 ++++++++++++++++++++++++++++
+ include/linux/mtd/rawnand.h | 112 ++++++++++++
+ 2 files changed, 367 insertions(+)
+
+diff --git a/drivers/mtd/nand/raw/nand_timings.c b/drivers/mtd/nand/raw/nand_timings.c
+index 94d832646487..481b56d5f60d 100644
+--- a/drivers/mtd/nand/raw/nand_timings.c
++++ b/drivers/mtd/nand/raw/nand_timings.c
+@@ -292,6 +292,261 @@ static const struct nand_interface_config onfi_sdr_timings[] = {
+ },
+ };
+
++static const struct nand_interface_config onfi_nvddr_timings[] = {
++ /* Mode 0 */
++ {
++ .type = NAND_NVDDR_IFACE,
++ .timings.mode = 0,
++ .timings.nvddr = {
++ .tCCS_min = 500000,
++ .tR_max = 200000000,
++ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tAC_min = 3000,
++ .tAC_max = 25000,
++ .tADL_min = 400000,
++ .tCAD_min = 45000,
++ .tCAH_min = 10000,
++ .tCALH_min = 10000,
++ .tCALS_min = 10000,
++ .tCAS_min = 10000,
++ .tCEH_min = 20000,
++ .tCH_min = 10000,
++ .tCK_min = 50000,
++ .tCS_min = 35000,
++ .tDH_min = 5000,
++ .tDQSCK_min = 3000,
++ .tDQSCK_max = 25000,
++ .tDQSD_min = 0,
++ .tDQSD_max = 18000,
++ .tDQSHZ_max = 20000,
++ .tDQSQ_max = 5000,
++ .tDS_min = 5000,
++ .tDSC_min = 50000,
++ .tFEAT_max = 1000000,
++ .tITC_max = 1000000,
++ .tQHS_max = 6000,
++ .tRHW_min = 100000,
++ .tRR_min = 20000,
++ .tRST_max = 500000000,
++ .tWB_max = 100000,
++ .tWHR_min = 80000,
++ .tWRCK_min = 20000,
++ .tWW_min = 100000,
++ },
++ },
++ /* Mode 1 */
++ {
++ .type = NAND_NVDDR_IFACE,
++ .timings.mode = 1,
++ .timings.nvddr = {
++ .tCCS_min = 500000,
++ .tR_max = 200000000,
++ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tAC_min = 3000,
++ .tAC_max = 25000,
++ .tADL_min = 400000,
++ .tCAD_min = 45000,
++ .tCAH_min = 5000,
++ .tCALH_min = 5000,
++ .tCALS_min = 5000,
++ .tCAS_min = 5000,
++ .tCEH_min = 20000,
++ .tCH_min = 5000,
++ .tCK_min = 30000,
++ .tCS_min = 25000,
++ .tDH_min = 2500,
++ .tDQSCK_min = 3000,
++ .tDQSCK_max = 25000,
++ .tDQSD_min = 0,
++ .tDQSD_max = 18000,
++ .tDQSHZ_max = 20000,
++ .tDQSQ_max = 2500,
++ .tDS_min = 3000,
++ .tDSC_min = 30000,
++ .tFEAT_max = 1000000,
++ .tITC_max = 1000000,
++ .tQHS_max = 3000,
++ .tRHW_min = 100000,
++ .tRR_min = 20000,
++ .tRST_max = 500000000,
++ .tWB_max = 100000,
++ .tWHR_min = 80000,
++ .tWRCK_min = 20000,
++ .tWW_min = 100000,
++ },
++ },
++ /* Mode 2 */
++ {
++ .type = NAND_NVDDR_IFACE,
++ .timings.mode = 2,
++ .timings.nvddr = {
++ .tCCS_min = 500000,
++ .tR_max = 200000000,
++ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tAC_min = 3000,
++ .tAC_max = 25000,
++ .tADL_min = 400000,
++ .tCAD_min = 45000,
++ .tCAH_min = 4000,
++ .tCALH_min = 4000,
++ .tCALS_min = 4000,
++ .tCAS_min = 4000,
++ .tCEH_min = 20000,
++ .tCH_min = 4000,
++ .tCK_min = 20000,
++ .tCS_min = 15000,
++ .tDH_min = 1700,
++ .tDQSCK_min = 3000,
++ .tDQSCK_max = 25000,
++ .tDQSD_min = 0,
++ .tDQSD_max = 18000,
++ .tDQSHZ_max = 20000,
++ .tDQSQ_max = 1700,
++ .tDS_min = 2000,
++ .tDSC_min = 20000,
++ .tFEAT_max = 1000000,
++ .tITC_max = 1000000,
++ .tQHS_max = 2000,
++ .tRHW_min = 100000,
++ .tRR_min = 20000,
++ .tRST_max = 500000000,
++ .tWB_max = 100000,
++ .tWHR_min = 80000,
++ .tWRCK_min = 20000,
++ .tWW_min = 100000,
++ },
++ },
++ /* Mode 3 */
++ {
++ .type = NAND_NVDDR_IFACE,
++ .timings.mode = 3,
++ .timings.nvddr = {
++ .tCCS_min = 500000,
++ .tR_max = 200000000,
++ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tAC_min = 3000,
++ .tAC_max = 25000,
++ .tADL_min = 400000,
++ .tCAD_min = 45000,
++ .tCAH_min = 3000,
++ .tCALH_min = 3000,
++ .tCALS_min = 3000,
++ .tCAS_min = 3000,
++ .tCEH_min = 20000,
++ .tCH_min = 3000,
++ .tCK_min = 15000,
++ .tCS_min = 15000,
++ .tDH_min = 1300,
++ .tDQSCK_min = 3000,
++ .tDQSCK_max = 25000,
++ .tDQSD_min = 0,
++ .tDQSD_max = 18000,
++ .tDQSHZ_max = 20000,
++ .tDQSQ_max = 1300,
++ .tDS_min = 1500,
++ .tDSC_min = 15000,
++ .tFEAT_max = 1000000,
++ .tITC_max = 1000000,
++ .tQHS_max = 1500,
++ .tRHW_min = 100000,
++ .tRR_min = 20000,
++ .tRST_max = 500000000,
++ .tWB_max = 100000,
++ .tWHR_min = 80000,
++ .tWRCK_min = 20000,
++ .tWW_min = 100000,
++ },
++ },
++ /* Mode 4 */
++ {
++ .type = NAND_NVDDR_IFACE,
++ .timings.mode = 4,
++ .timings.nvddr = {
++ .tCCS_min = 500000,
++ .tR_max = 200000000,
++ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tAC_min = 3000,
++ .tAC_max = 25000,
++ .tADL_min = 400000,
++ .tCAD_min = 45000,
++ .tCAH_min = 2500,
++ .tCALH_min = 2500,
++ .tCALS_min = 2500,
++ .tCAS_min = 2500,
++ .tCEH_min = 20000,
++ .tCH_min = 2500,
++ .tCK_min = 12000,
++ .tCS_min = 15000,
++ .tDH_min = 1100,
++ .tDQSCK_min = 3000,
++ .tDQSCK_max = 25000,
++ .tDQSD_min = 0,
++ .tDQSD_max = 18000,
++ .tDQSHZ_max = 20000,
++ .tDQSQ_max = 1000,
++ .tDS_min = 1100,
++ .tDSC_min = 12000,
++ .tFEAT_max = 1000000,
++ .tITC_max = 1000000,
++ .tQHS_max = 1200,
++ .tRHW_min = 100000,
++ .tRR_min = 20000,
++ .tRST_max = 500000000,
++ .tWB_max = 100000,
++ .tWHR_min = 80000,
++ .tWRCK_min = 20000,
++ .tWW_min = 100000,
++ },
++ },
++ /* Mode 5 */
++ {
++ .type = NAND_NVDDR_IFACE,
++ .timings.mode = 5,
++ .timings.nvddr = {
++ .tCCS_min = 500000,
++ .tR_max = 200000000,
++ .tPROG_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tBERS_max = 1000000ULL * ONFI_DYN_TIMING_MAX,
++ .tAC_min = 3000,
++ .tAC_max = 25000,
++ .tADL_min = 400000,
++ .tCAD_min = 45000,
++ .tCAH_min = 2000,
++ .tCALH_min = 2000,
++ .tCALS_min = 2000,
++ .tCAS_min = 2000,
++ .tCEH_min = 20000,
++ .tCH_min = 2000,
++ .tCK_min = 10000,
++ .tCS_min = 15000,
++ .tDH_min = 900,
++ .tDQSCK_min = 3000,
++ .tDQSCK_max = 25000,
++ .tDQSD_min = 0,
++ .tDQSD_max = 18000,
++ .tDQSHZ_max = 20000,
++ .tDQSQ_max = 850,
++ .tDS_min = 900,
++ .tDSC_min = 10000,
++ .tFEAT_max = 1000000,
++ .tITC_max = 1000000,
++ .tQHS_max = 1000,
++ .tRHW_min = 100000,
++ .tRR_min = 20000,
++ .tRST_max = 500000000,
++ .tWB_max = 100000,
++ .tWHR_min = 80000,
++ .tWRCK_min = 20000,
++ .tWW_min = 100000,
++ },
++ },
++};
++
+ /* All NAND chips share the same reset data interface: SDR mode 0 */
+ const struct nand_interface_config *nand_get_reset_interface_config(void)
+ {
+diff --git a/include/linux/mtd/rawnand.h b/include/linux/mtd/rawnand.h
+index 75535036b126..2044fbd55d73 100644
+--- a/include/linux/mtd/rawnand.h
++++ b/include/linux/mtd/rawnand.h
+@@ -474,12 +474,100 @@ struct nand_sdr_timings {
+ u32 tWW_min;
+ };
+
++/**
++ * struct nand_nvddr_timings - NV-DDR NAND chip timings
++ *
++ * This struct defines the timing requirements of a NV-DDR NAND data interface.
++ * These information can be found in every NAND datasheets and the timings
++ * meaning are described in the ONFI specifications:
++ * https://media-www.micron.com/-/media/client/onfi/specs/onfi_4_1_gold.pdf
++ * (chapter 4.18.2 NV-DDR)
++ *
++ * All these timings are expressed in picoseconds.
++ *
++ * @tBERS_max: Block erase time
++ * @tCCS_min: Change column setup time
++ * @tPROG_max: Page program time
++ * @tR_max: Page read time
++ * @tAC_min: Access window of DQ[7:0] from CLK
++ * @tAC_max: Access window of DQ[7:0] from CLK
++ * @tADL_min: ALE to data loading time
++ * @tCAD_min: Command, Address, Data delay
++ * @tCAH_min: Command/Address DQ hold time
++ * @tCALH_min: W/R_n, CLE and ALE hold time
++ * @tCALS_min: W/R_n, CLE and ALE setup time
++ * @tCAS_min: Command/address DQ setup time
++ * @tCEH_min: CE# high hold time
++ * @tCH_min: CE# hold time
++ * @tCK_min: Average clock cycle time
++ * @tCS_min: CE# setup time
++ * @tDH_min: Data hold time
++ * @tDQSCK_min: Start of the access window of DQS from CLK
++ * @tDQSCK_max: End of the access window of DQS from CLK
++ * @tDQSD_min: Min W/R_n low to DQS/DQ driven by device
++ * @tDQSD_max: Max W/R_n low to DQS/DQ driven by device
++ * @tDQSHZ_max: W/R_n high to DQS/DQ tri-state by device
++ * @tDQSQ_max: DQS-DQ skew, DQS to last DQ valid, per access
++ * @tDS_min: Data setup time
++ * @tDSC_min: DQS cycle time
++ * @tFEAT_max: Busy time for Set Features and Get Features
++ * @tITC_max: Interface and Timing Mode Change time
++ * @tQHS_max: Data hold skew factor
++ * @tRHW_min: Data output cycle to command, address, or data input cycle
++ * @tRR_min: Ready to RE# low (data only)
++ * @tRST_max: Device reset time, measured from the falling edge of R/B# to the
++ * rising edge of R/B#.
++ * @tWB_max: WE# high to SR[6] low
++ * @tWHR_min: WE# high to RE# low
++ * @tWRCK_min: W/R_n low to data output cycle
++ * @tWW_min: WP# transition to WE# low
++ */
++struct nand_nvddr_timings {
++ u64 tBERS_max;
++ u32 tCCS_min;
++ u64 tPROG_max;
++ u64 tR_max;
++ u32 tAC_min;
++ u32 tAC_max;
++ u32 tADL_min;
++ u32 tCAD_min;
++ u32 tCAH_min;
++ u32 tCALH_min;
++ u32 tCALS_min;
++ u32 tCAS_min;
++ u32 tCEH_min;
++ u32 tCH_min;
++ u32 tCK_min;
++ u32 tCS_min;
++ u32 tDH_min;
++ u32 tDQSCK_min;
++ u32 tDQSCK_max;
++ u32 tDQSD_min;
++ u32 tDQSD_max;
++ u32 tDQSHZ_max;
++ u32 tDQSQ_max;
++ u32 tDS_min;
++ u32 tDSC_min;
++ u32 tFEAT_max;
++ u32 tITC_max;
++ u32 tQHS_max;
++ u32 tRHW_min;
++ u32 tRR_min;
++ u32 tRST_max;
++ u32 tWB_max;
++ u32 tWHR_min;
++ u32 tWRCK_min;
++ u32 tWW_min;
++};
++
+ /**
+ * enum nand_interface_type - NAND interface type
+ * @NAND_SDR_IFACE: Single Data Rate interface
++ * @NAND_NVDDR_IFACE: Double Data Rate interface
+ */
+ enum nand_interface_type {
+ NAND_SDR_IFACE,
++ NAND_NVDDR_IFACE,
+ };
+
+ /**
+@@ -488,6 +576,7 @@ enum nand_interface_type {
+ * @timings: The timing information
+ * @timings.mode: Timing mode as defined in the specification
+ * @timings.sdr: Use it when @type is %NAND_SDR_IFACE.
++ * @timings.nvddr: Use it when @type is %NAND_NVDDR_IFACE.
+ */
+ struct nand_interface_config {
+ enum nand_interface_type type;
+@@ -495,6 +584,7 @@ struct nand_interface_config {
+ unsigned int mode;
+ union {
+ struct nand_sdr_timings sdr;
++ struct nand_nvddr_timings nvddr;
+ };
+ } timings;
+ };
+@@ -508,6 +598,15 @@ static bool nand_interface_is_sdr(const struct nand_interface_config *conf)
+ return conf->type == NAND_SDR_IFACE;
+ }
+
++/**
++ * nand_interface_is_nvddr - get the interface type
++ * @conf: The data interface
++ */
++static bool nand_interface_is_nvddr(const struct nand_interface_config *conf)
++{
++ return conf->type == NAND_NVDDR_IFACE;
++}
++
+ /**
+ * nand_get_sdr_timings - get SDR timing from data interface
+ * @conf: The data interface
+@@ -521,6 +620,19 @@ nand_get_sdr_timings(const struct nand_interface_config *conf)
+ return &conf->timings.sdr;
+ }
+
++/**
++ * nand_get_nvddr_timings - get NV-DDR timing from data interface
++ * @conf: The data interface
++ */
++static inline const struct nand_nvddr_timings *
++nand_get_nvddr_timings(const struct nand_interface_config *conf)
++{
++ if (!nand_interface_is_nvddr(conf))
++ return ERR_PTR(-EINVAL);
++
++ return &conf->timings.nvddr;
++}
++
+ /**
+ * struct nand_op_cmd_instr - Definition of a command instruction
+ * @opcode: the command to issue in one cycle
+--
+2.35.1
+
--- /dev/null
+From 18d1d99d0c89cda1fc0b008ad27cda52a96cf609 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 May 2021 23:37:30 +0200
+Subject: mtd: rawnand: arasan: Check the proposed data interface is supported
+
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+
+[ Upstream commit 4dd7ef970bee8a93e1817ec028a7e26aef046d0d ]
+
+Check the data interface is supported in ->setup_interface() before
+acknowledging the timings.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20210505213750.257417-3-miquel.raynal@bootlin.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/nand/raw/arasan-nand-controller.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
+index cea57de5e6cd..f9fb3b7a3ec3 100644
+--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
++++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
+@@ -884,6 +884,11 @@ static int anfc_setup_interface(struct nand_chip *chip, int target,
+ struct anand *anand = to_anand(chip);
+ struct arasan_nfc *nfc = to_anfc(chip->controller);
+ struct device_node *np = nfc->dev->of_node;
++ const struct nand_sdr_timings *sdr;
++
++ sdr = nand_get_sdr_timings(conf);
++ if (IS_ERR(sdr))
++ return PTR_ERR(sdr);
+
+ if (target < 0)
+ return 0;
+--
+2.35.1
+
--- /dev/null
+From 2932ebe6de497d85f7ce65c5f314088405683f2b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 May 2021 23:37:48 +0200
+Subject: mtd: rawnand: arasan: Fix a macro parameter
+
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+
+[ Upstream commit 698ddeb89e01840dec05ffdb538468782e641a56 ]
+
+This macro is not yet being used so the compilers never complained
+about it.
+
+Fix the macro before using it.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20210505213750.257417-21-miquel.raynal@bootlin.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/nand/raw/arasan-nand-controller.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
+index f9fb3b7a3ec3..a3d4ee988394 100644
+--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
++++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
+@@ -91,7 +91,7 @@
+
+ #define DATA_INTERFACE_REG 0x6C
+ #define DIFACE_SDR_MODE(x) FIELD_PREP(GENMASK(2, 0), (x))
+-#define DIFACE_DDR_MODE(x) FIELD_PREP(GENMASK(5, 3), (X))
++#define DIFACE_DDR_MODE(x) FIELD_PREP(GENMASK(5, 3), (x))
+ #define DIFACE_SDR 0
+ #define DIFACE_NVDDR BIT(9)
+
+--
+2.35.1
+
--- /dev/null
+From 6c260b50b8629c269e2b747153a2e68909a8abf7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Jun 2022 21:18:24 +0530
+Subject: mtd: rawnand: arasan: Fix clock rate in NV-DDR
+
+From: Olga Kitaina <okitain@gmail.com>
+
+[ Upstream commit e16eceea863b417fd328588b1be1a79de0bc937f ]
+
+According to the Arasan NAND controller spec, the flash clock rate for SDR
+must be <= 100 MHz, while for NV-DDR it must be the same as the rate of the
+CLK line for the mode. The driver previously always set 100 MHz for NV-DDR,
+which would result in incorrect behavior for NV-DDR modes 0-4.
+
+The appropriate clock rate can be calculated from the NV-DDR timing
+parameters as 1/tCK, or for rates measured in picoseconds,
+10^12 / nand_nvddr_timings->tCK_min.
+
+Fixes: 197b88fecc50 ("mtd: rawnand: arasan: Add new Arasan NAND controller")
+CC: stable@vger.kernel.org # 5.8+
+Signed-off-by: Olga Kitaina <okitain@gmail.com>
+Signed-off-by: Amit Kumar Mahapatra <amit.kumar-mahapatra@xilinx.com>
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20220628154824.12222-3-amit.kumar-mahapatra@xilinx.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/nand/raw/arasan-nand-controller.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
+index f926d658192b..50643c6f33f4 100644
+--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
++++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
+@@ -907,7 +907,13 @@ static int anfc_setup_interface(struct nand_chip *chip, int target,
+ anand->timings = DIFACE_NVDDR |
+ DIFACE_DDR_MODE(conf->timings.mode);
+
+- anand->clk = ANFC_XLNX_SDR_DFLT_CORE_CLK;
++ if (nand_interface_is_sdr(conf)) {
++ anand->clk = ANFC_XLNX_SDR_DFLT_CORE_CLK;
++ } else {
++ /* ONFI timings are defined in picoseconds */
++ anand->clk = div_u64((u64)NSEC_PER_SEC * 1000,
++ conf->timings.nvddr.tCK_min);
++ }
+
+ /*
+ * Due to a hardware bug in the ZynqMP SoC, SDR timing modes 0-1 work
+--
+2.35.1
+
--- /dev/null
+From a0cb61eb7305f923a85367665d80502258ffa652 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 5 May 2021 23:37:50 +0200
+Subject: mtd: rawnand: arasan: Support NV-DDR interface
+
+From: Miquel Raynal <miquel.raynal@bootlin.com>
+
+[ Upstream commit 4edde60314587382e42141df2f41ca968dc20737 ]
+
+Add support for the NV-DDR interface.
+
+Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
+Link: https://lore.kernel.org/linux-mtd/20210505213750.257417-23-miquel.raynal@bootlin.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mtd/nand/raw/arasan-nand-controller.c | 27 ++++++++++++++-----
+ 1 file changed, 20 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/mtd/nand/raw/arasan-nand-controller.c b/drivers/mtd/nand/raw/arasan-nand-controller.c
+index a3d4ee988394..f926d658192b 100644
+--- a/drivers/mtd/nand/raw/arasan-nand-controller.c
++++ b/drivers/mtd/nand/raw/arasan-nand-controller.c
+@@ -885,25 +885,38 @@ static int anfc_setup_interface(struct nand_chip *chip, int target,
+ struct arasan_nfc *nfc = to_anfc(chip->controller);
+ struct device_node *np = nfc->dev->of_node;
+ const struct nand_sdr_timings *sdr;
+-
+- sdr = nand_get_sdr_timings(conf);
+- if (IS_ERR(sdr))
+- return PTR_ERR(sdr);
++ const struct nand_nvddr_timings *nvddr;
++
++ if (nand_interface_is_nvddr(conf)) {
++ nvddr = nand_get_nvddr_timings(conf);
++ if (IS_ERR(nvddr))
++ return PTR_ERR(nvddr);
++ } else {
++ sdr = nand_get_sdr_timings(conf);
++ if (IS_ERR(sdr))
++ return PTR_ERR(sdr);
++ }
+
+ if (target < 0)
+ return 0;
+
+- anand->timings = DIFACE_SDR | DIFACE_SDR_MODE(conf->timings.mode);
++ if (nand_interface_is_sdr(conf))
++ anand->timings = DIFACE_SDR |
++ DIFACE_SDR_MODE(conf->timings.mode);
++ else
++ anand->timings = DIFACE_NVDDR |
++ DIFACE_DDR_MODE(conf->timings.mode);
++
+ anand->clk = ANFC_XLNX_SDR_DFLT_CORE_CLK;
+
+ /*
+ * Due to a hardware bug in the ZynqMP SoC, SDR timing modes 0-1 work
+ * with f > 90MHz (default clock is 100MHz) but signals are unstable
+ * with higher modes. Hence we decrease a little bit the clock rate to
+- * 80MHz when using modes 2-5 with this SoC.
++ * 80MHz when using SDR modes 2-5 with this SoC.
+ */
+ if (of_device_is_compatible(np, "xlnx,zynqmp-nand-controller") &&
+- conf->timings.mode >= 2)
++ nand_interface_is_sdr(conf) && conf->timings.mode >= 2)
+ anand->clk = ANFC_XLNX_SDR_HS_CORE_CLK;
+
+ return 0;
+--
+2.35.1
+
--- /dev/null
+From 693f066006288534e1ca5f12d7b6a1603b7b8bda Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 9 May 2022 18:14:41 +0000
+Subject: PCI/AER: Iterate over error counters instead of error strings
+
+From: Mohamed Khalfella <mkhalfella@purestorage.com>
+
+[ Upstream commit 5e6ae050955b566484f3cc6a66e3925eae87a0ed ]
+
+Previously we iterated over AER stat *names*, e.g.,
+aer_correctable_error_string[32], but the actual stat *counters* may not be
+that large, e.g., pdev->aer_stats->dev_cor_errs[16], which means that we
+printed junk in the sysfs stats files.
+
+Iterate over the stat counter arrays instead of the names to avoid this
+junk.
+
+Also, added a build time check to make sure all
+counters have entries in strings array.
+
+Fixes: 0678e3109a3c ("PCI/AER: Simplify __aer_print_error()")
+Link: https://lore.kernel.org/r/20220509181441.31884-1-mkhalfella@purestorage.com
+Reported-by: Meeta Saggi <msaggi@purestorage.com>
+Signed-off-by: Mohamed Khalfella <mkhalfella@purestorage.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Meeta Saggi <msaggi@purestorage.com>
+Reviewed-by: Eric Badger <ebadger@purestorage.com>
+Cc: stable@vger.kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/aer.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
+index 2ab708ab7218..9564b74003f0 100644
+--- a/drivers/pci/pcie/aer.c
++++ b/drivers/pci/pcie/aer.c
+@@ -538,7 +538,7 @@ static const char *aer_agent_string[] = {
+ struct pci_dev *pdev = to_pci_dev(dev); \
+ u64 *stats = pdev->aer_stats->stats_array; \
+ \
+- for (i = 0; i < ARRAY_SIZE(strings_array); i++) { \
++ for (i = 0; i < ARRAY_SIZE(pdev->aer_stats->stats_array); i++) {\
+ if (strings_array[i]) \
+ str += sprintf(str, "%s %llu\n", \
+ strings_array[i], stats[i]); \
+@@ -1338,6 +1338,11 @@ static int aer_probe(struct pcie_device *dev)
+ struct device *device = &dev->device;
+ struct pci_dev *port = dev->port;
+
++ BUILD_BUG_ON(ARRAY_SIZE(aer_correctable_error_string) <
++ AER_MAX_TYPEOF_COR_ERRS);
++ BUILD_BUG_ON(ARRAY_SIZE(aer_uncorrectable_error_string) <
++ AER_MAX_TYPEOF_UNCOR_ERRS);
++
+ /* Limit to Root Ports or Root Complex Event Collectors */
+ if ((pci_pcie_type(port) != PCI_EXP_TYPE_RC_EC) &&
+ (pci_pcie_type(port) != PCI_EXP_TYPE_ROOT_PORT))
+--
+2.35.1
+
--- /dev/null
+From 940b28e989ee3668c245fa1ade17e5229152c4c1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Nov 2020 16:10:22 -0800
+Subject: PCI/AER: Write AER Capability only when we control it
+
+From: Sean V Kelley <sean.v.kelley@intel.com>
+
+[ Upstream commit 50cc18fcd3053fb46a09db5a39e6516e9560f765 ]
+
+If an OS has not been granted AER control via _OSC, it should not make
+changes to PCI_ERR_ROOT_COMMAND and PCI_ERR_ROOT_STATUS related registers.
+Per section 4.5.1 of the System Firmware Intermediary (SFI) _OSC and DPC
+Updates ECN [1], this bit also covers these aspects of the PCI Express
+Advanced Error Reporting. Based on the above and earlier discussion [2],
+make the following changes:
+
+Add a check for the native case (i.e., AER control via _OSC)
+
+Note that the previous "clear, reset, enable" order suggests that the reset
+might cause errors that we should ignore. After this commit, those errors
+(if any) will remain logged in the PCI_ERR_ROOT_STATUS register.
+
+[1] System Firmware Intermediary (SFI) _OSC and DPC Updates ECN, Feb 24,
+ 2020, affecting PCI Firmware Specification, Rev. 3.2
+ https://members.pcisig.com/wg/PCI-SIG/document/14076
+[2] https://lore.kernel.org/linux-pci/20201020162820.GA370938@bjorn-Precision-5520/
+
+Link: https://lore.kernel.org/r/20201121001036.8560-2-sean.v.kelley@intel.com
+Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # non-native/no RCEC
+Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/aer.c | 29 ++++++++++++++++-------------
+ 1 file changed, 16 insertions(+), 13 deletions(-)
+
+diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
+index c40546eeecb3..61f78b20b0cf 100644
+--- a/drivers/pci/pcie/aer.c
++++ b/drivers/pci/pcie/aer.c
+@@ -1366,23 +1366,26 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
+ u32 reg32;
+ int rc;
+
+-
+- /* Disable Root's interrupt in response to error messages */
+- pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32);
+- reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
+- pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32);
++ if (pcie_aer_is_native(dev)) {
++ /* Disable Root's interrupt in response to error messages */
++ pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32);
++ reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
++ pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32);
++ }
+
+ rc = pci_bus_error_reset(dev);
+- pci_info(dev, "Root Port link has been reset\n");
++ pci_info(dev, "Root Port link has been reset (%d)\n", rc);
+
+- /* Clear Root Error Status */
+- pci_read_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, ®32);
+- pci_write_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, reg32);
++ if (pcie_aer_is_native(dev)) {
++ /* Clear Root Error Status */
++ pci_read_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, ®32);
++ pci_write_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, reg32);
+
+- /* Enable Root Port's interrupt in response to error messages */
+- pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32);
+- reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
+- pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32);
++ /* Enable Root Port's interrupt in response to error messages */
++ pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32);
++ reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
++ pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32);
++ }
+
+ return rc ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
+ }
+--
+2.35.1
+
--- /dev/null
+From 8af9dc0aa74438338b1e2ee947f150c3230d4f41 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Nov 2020 16:10:30 -0800
+Subject: PCI/ERR: Add pci_walk_bridge() to pcie_do_recovery()
+
+From: Sean V Kelley <sean.v.kelley@intel.com>
+
+[ Upstream commit 05e9ae19ab83881a0f33025bd1288e41e552a34b ]
+
+Consolidate subordinate bus checks with pci_walk_bus() into
+pci_walk_bridge() for walking below potentially AER affected bridges.
+
+Link: https://lore.kernel.org/r/20201121001036.8560-10-sean.v.kelley@intel.com
+Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # non-native/no RCEC
+Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/err.c | 30 +++++++++++++++++++++++-------
+ 1 file changed, 23 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
+index 931e75f2549d..8b53aecdb43d 100644
+--- a/drivers/pci/pcie/err.c
++++ b/drivers/pci/pcie/err.c
+@@ -146,13 +146,30 @@ static int report_resume(struct pci_dev *dev, void *data)
+ return 0;
+ }
+
++/**
++ * pci_walk_bridge - walk bridges potentially AER affected
++ * @bridge: bridge which may be a Port
++ * @cb: callback to be called for each device found
++ * @userdata: arbitrary pointer to be passed to callback
++ *
++ * If the device provided is a bridge, walk the subordinate bus, including
++ * any bridged devices on buses under this bus. Call the provided callback
++ * on each device found.
++ */
++static void pci_walk_bridge(struct pci_dev *bridge,
++ int (*cb)(struct pci_dev *, void *),
++ void *userdata)
++{
++ if (bridge->subordinate)
++ pci_walk_bus(bridge->subordinate, cb, userdata);
++}
++
+ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ pci_channel_state_t state,
+ pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev))
+ {
+ int type = pci_pcie_type(dev);
+ struct pci_dev *bridge;
+- struct pci_bus *bus;
+ pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
+
+ /*
+@@ -165,23 +182,22 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ else
+ bridge = pci_upstream_bridge(dev);
+
+- bus = bridge->subordinate;
+ pci_dbg(bridge, "broadcast error_detected message\n");
+ if (state == pci_channel_io_frozen) {
+- pci_walk_bus(bus, report_frozen_detected, &status);
++ pci_walk_bridge(bridge, report_frozen_detected, &status);
+ status = reset_subordinates(bridge);
+ if (status != PCI_ERS_RESULT_RECOVERED) {
+ pci_warn(bridge, "subordinate device reset failed\n");
+ goto failed;
+ }
+ } else {
+- pci_walk_bus(bus, report_normal_detected, &status);
++ pci_walk_bridge(bridge, report_normal_detected, &status);
+ }
+
+ if (status == PCI_ERS_RESULT_CAN_RECOVER) {
+ status = PCI_ERS_RESULT_RECOVERED;
+ pci_dbg(bridge, "broadcast mmio_enabled message\n");
+- pci_walk_bus(bus, report_mmio_enabled, &status);
++ pci_walk_bridge(bridge, report_mmio_enabled, &status);
+ }
+
+ if (status == PCI_ERS_RESULT_NEED_RESET) {
+@@ -192,14 +208,14 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ */
+ status = PCI_ERS_RESULT_RECOVERED;
+ pci_dbg(bridge, "broadcast slot_reset message\n");
+- pci_walk_bus(bus, report_slot_reset, &status);
++ pci_walk_bridge(bridge, report_slot_reset, &status);
+ }
+
+ if (status != PCI_ERS_RESULT_RECOVERED)
+ goto failed;
+
+ pci_dbg(bridge, "broadcast resume message\n");
+- pci_walk_bus(bus, report_resume, &status);
++ pci_walk_bridge(bridge, report_resume, &status);
+
+ if (pcie_aer_is_native(bridge))
+ pcie_clear_device_status(bridge);
+--
+2.35.1
+
--- /dev/null
+From f1938900858d806b7d1cdd278c82554c2adcb7b9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Nov 2020 16:10:29 -0800
+Subject: PCI/ERR: Avoid negated conditional for clarity
+
+From: Sean V Kelley <sean.v.kelley@intel.com>
+
+[ Upstream commit 3d7d8fc78f4b504819882278fcfe10784eb985fa ]
+
+Reverse the sense of the Root Port/Downstream Port conditional for clarity.
+No functional change intended.
+
+Link: https://lore.kernel.org/r/20201121001036.8560-9-sean.v.kelley@intel.com
+Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # non-native/no RCEC
+Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/err.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
+index 46a5b84f8842..931e75f2549d 100644
+--- a/drivers/pci/pcie/err.c
++++ b/drivers/pci/pcie/err.c
+@@ -159,11 +159,11 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ * Error recovery runs on all subordinates of the bridge. If the
+ * bridge detected the error, it is cleared at the end.
+ */
+- if (!(type == PCI_EXP_TYPE_ROOT_PORT ||
+- type == PCI_EXP_TYPE_DOWNSTREAM))
+- bridge = pci_upstream_bridge(dev);
+- else
++ if (type == PCI_EXP_TYPE_ROOT_PORT ||
++ type == PCI_EXP_TYPE_DOWNSTREAM)
+ bridge = dev;
++ else
++ bridge = pci_upstream_bridge(dev);
+
+ bus = bridge->subordinate;
+ pci_dbg(bridge, "broadcast error_detected message\n");
+--
+2.35.1
+
--- /dev/null
+From d3ff05f10a6e5e4c0b3df84b27df1b3b2ee863f2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Nov 2020 16:10:23 -0800
+Subject: PCI/ERR: Bind RCEC devices to the Root Port driver
+
+From: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+
+[ Upstream commit c9d659b60770db94b898f94947192a94bbf95c5c ]
+
+If a Root Complex Integrated Endpoint (RCiEP) is implemented, it may signal
+errors through a Root Complex Event Collector (RCEC). Each RCiEP must be
+associated with no more than one RCEC.
+
+For an RCEC (which is technically not a Bridge), error messages "received"
+from associated RCiEPs must be enabled for "transmission" in order to cause
+a System Error via the Root Control register or (when the Advanced Error
+Reporting Capability is present) reporting via the Root Error Command
+register and logging in the Root Error Status register and Error Source
+Identification register.
+
+Given the commonality with Root Ports and the need to also support AER and
+PME services for RCECs, extend the Root Port driver to support RCEC devices
+by adding the RCEC Class ID to the driver structure.
+
+Co-developed-by: Sean V Kelley <sean.v.kelley@intel.com>
+Link: https://lore.kernel.org/r/20201121001036.8560-3-sean.v.kelley@intel.com
+Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # non-native/no RCEC
+Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com>
+Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/portdrv_pci.c | 5 ++++-
+ include/linux/pci_ids.h | 1 +
+ include/uapi/linux/pci_regs.h | 7 +++++++
+ 3 files changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
+index d4559cf88f79..26259630fd10 100644
+--- a/drivers/pci/pcie/portdrv_pci.c
++++ b/drivers/pci/pcie/portdrv_pci.c
+@@ -106,7 +106,8 @@ static int pcie_portdrv_probe(struct pci_dev *dev,
+ if (!pci_is_pcie(dev) ||
+ ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) &&
+ (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) &&
+- (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM)))
++ (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM) &&
++ (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_EC)))
+ return -ENODEV;
+
+ status = pcie_port_device_register(dev);
+@@ -195,6 +196,8 @@ static const struct pci_device_id port_pci_ids[] = {
+ { PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x00), ~0) },
+ /* subtractive decode PCI-to-PCI bridge, class type is 060401h */
+ { PCI_DEVICE_CLASS(((PCI_CLASS_BRIDGE_PCI << 8) | 0x01), ~0) },
++ /* handle any Root Complex Event Collector */
++ { PCI_DEVICE_CLASS(((PCI_CLASS_SYSTEM_RCEC << 8) | 0x00), ~0) },
+ { },
+ };
+
+diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
+index 635a9243cce0..ece7c28affa0 100644
+--- a/include/linux/pci_ids.h
++++ b/include/linux/pci_ids.h
+@@ -81,6 +81,7 @@
+ #define PCI_CLASS_SYSTEM_RTC 0x0803
+ #define PCI_CLASS_SYSTEM_PCI_HOTPLUG 0x0804
+ #define PCI_CLASS_SYSTEM_SDHCI 0x0805
++#define PCI_CLASS_SYSTEM_RCEC 0x0807
+ #define PCI_CLASS_SYSTEM_OTHER 0x0880
+
+ #define PCI_BASE_CLASS_INPUT 0x09
+diff --git a/include/uapi/linux/pci_regs.h b/include/uapi/linux/pci_regs.h
+index 142b184eca8b..7e0d526dd96f 100644
+--- a/include/uapi/linux/pci_regs.h
++++ b/include/uapi/linux/pci_regs.h
+@@ -837,6 +837,13 @@
+ #define PCI_PWR_CAP_BUDGET(x) ((x) & 1) /* Included in system budget */
+ #define PCI_EXT_CAP_PWR_SIZEOF 16
+
++/* Root Complex Event Collector Endpoint Association */
++#define PCI_RCEC_RCIEP_BITMAP 4 /* Associated Bitmap for RCiEPs */
++#define PCI_RCEC_BUSN 8 /* RCEC Associated Bus Numbers */
++#define PCI_RCEC_BUSN_REG_VER 0x02 /* Least version with BUSN present */
++#define PCI_RCEC_BUSN_NEXT(x) (((x) >> 8) & 0xff)
++#define PCI_RCEC_BUSN_LAST(x) (((x) >> 16) & 0xff)
++
+ /* Vendor-Specific (VSEC, PCI_EXT_CAP_ID_VNDR) */
+ #define PCI_VNDR_HEADER 4 /* Vendor-Specific Header */
+ #define PCI_VNDR_HEADER_ID(x) ((x) & 0xffff)
+--
+2.35.1
+
--- /dev/null
+From d227b907953e91855436c2034591b3c21ea0de9d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Dec 2020 11:26:29 -0600
+Subject: PCI/ERR: Recover from RCEC AER errors
+
+From: Sean V Kelley <sean.v.kelley@intel.com>
+
+[ Upstream commit a175102b0a82fc57853a9e611c42d1d6172e5180 ]
+
+A Root Complex Event Collector (RCEC) collects and signals AER errors that
+were detected by Root Complex Integrated Endpoints (RCiEPs), but it may
+also signal errors it detects itself. This is analogous to errors detected
+and signaled by a Root Port.
+
+Update the AER service driver to claim RCECs in addition to Root Ports.
+Add support for handling RCEC-detected AER errors. This does not
+include handling RCiEP-detected errors that are signaled by the RCEC.
+
+Note that we expect these errors only from the native AER and APEI paths,
+not from DPC or EDR.
+
+[bhelgaas: split from combined RCEC/RCiEP patch, commit log]
+Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/aer.c | 58 +++++++++++++++++++++++++++++-------------
+ drivers/pci/pcie/err.c | 19 +++++++++++---
+ 2 files changed, 56 insertions(+), 21 deletions(-)
+
+diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
+index 72dbc193a25f..2ab708ab7218 100644
+--- a/drivers/pci/pcie/aer.c
++++ b/drivers/pci/pcie/aer.c
+@@ -305,7 +305,8 @@ int pci_aer_raw_clear_status(struct pci_dev *dev)
+ return -EIO;
+
+ port_type = pci_pcie_type(dev);
+- if (port_type == PCI_EXP_TYPE_ROOT_PORT) {
++ if (port_type == PCI_EXP_TYPE_ROOT_PORT ||
++ port_type == PCI_EXP_TYPE_RC_EC) {
+ pci_read_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, &status);
+ pci_write_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, status);
+ }
+@@ -600,7 +601,8 @@ static umode_t aer_stats_attrs_are_visible(struct kobject *kobj,
+ if ((a == &dev_attr_aer_rootport_total_err_cor.attr ||
+ a == &dev_attr_aer_rootport_total_err_fatal.attr ||
+ a == &dev_attr_aer_rootport_total_err_nonfatal.attr) &&
+- pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT)
++ ((pci_pcie_type(pdev) != PCI_EXP_TYPE_ROOT_PORT) &&
++ (pci_pcie_type(pdev) != PCI_EXP_TYPE_RC_EC)))
+ return 0;
+
+ return a->mode;
+@@ -1211,6 +1213,7 @@ static int set_device_error_reporting(struct pci_dev *dev, void *data)
+ int type = pci_pcie_type(dev);
+
+ if ((type == PCI_EXP_TYPE_ROOT_PORT) ||
++ (type == PCI_EXP_TYPE_RC_EC) ||
+ (type == PCI_EXP_TYPE_UPSTREAM) ||
+ (type == PCI_EXP_TYPE_DOWNSTREAM)) {
+ if (enable)
+@@ -1335,6 +1338,11 @@ static int aer_probe(struct pcie_device *dev)
+ struct device *device = &dev->device;
+ struct pci_dev *port = dev->port;
+
++ /* Limit to Root Ports or Root Complex Event Collectors */
++ if ((pci_pcie_type(port) != PCI_EXP_TYPE_RC_EC) &&
++ (pci_pcie_type(port) != PCI_EXP_TYPE_ROOT_PORT))
++ return -ENODEV;
++
+ rpc = devm_kzalloc(device, sizeof(struct aer_rpc), GFP_KERNEL);
+ if (!rpc)
+ return -ENOMEM;
+@@ -1356,36 +1364,52 @@ static int aer_probe(struct pcie_device *dev)
+ }
+
+ /**
+- * aer_root_reset - reset link on Root Port
+- * @dev: pointer to Root Port's pci_dev data structure
++ * aer_root_reset - reset Root Port hierarchy or RCEC
++ * @dev: pointer to Root Port or RCEC
+ *
+- * Invoked by Port Bus driver when performing link reset at Root Port.
++ * Invoked by Port Bus driver when performing reset.
+ */
+ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
+ {
+- int aer = dev->aer_cap;
++ int type = pci_pcie_type(dev);
++ struct pci_dev *root;
++ int aer;
++ struct pci_host_bridge *host = pci_find_host_bridge(dev->bus);
+ u32 reg32;
+ int rc;
+
+- if (pcie_aer_is_native(dev)) {
++ root = dev; /* device with Root Error registers */
++ aer = root->aer_cap;
++
++ if ((host->native_aer || pcie_ports_native) && aer) {
+ /* Disable Root's interrupt in response to error messages */
+- pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32);
++ pci_read_config_dword(root, aer + PCI_ERR_ROOT_COMMAND, ®32);
+ reg32 &= ~ROOT_PORT_INTR_ON_MESG_MASK;
+- pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32);
++ pci_write_config_dword(root, aer + PCI_ERR_ROOT_COMMAND, reg32);
+ }
+
+- rc = pci_bus_error_reset(dev);
+- pci_info(dev, "Root Port link has been reset (%d)\n", rc);
++ if (type == PCI_EXP_TYPE_RC_EC) {
++ if (pcie_has_flr(dev)) {
++ rc = pcie_flr(dev);
++ pci_info(dev, "has been reset (%d)\n", rc);
++ } else {
++ pci_info(dev, "not reset (no FLR support)\n");
++ rc = -ENOTTY;
++ }
++ } else {
++ rc = pci_bus_error_reset(dev);
++ pci_info(dev, "Root Port link has been reset (%d)\n", rc);
++ }
+
+- if (pcie_aer_is_native(dev)) {
++ if ((host->native_aer || pcie_ports_native) && aer) {
+ /* Clear Root Error Status */
+- pci_read_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, ®32);
+- pci_write_config_dword(dev, aer + PCI_ERR_ROOT_STATUS, reg32);
++ pci_read_config_dword(root, aer + PCI_ERR_ROOT_STATUS, ®32);
++ pci_write_config_dword(root, aer + PCI_ERR_ROOT_STATUS, reg32);
+
+ /* Enable Root Port's interrupt in response to error messages */
+- pci_read_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, ®32);
++ pci_read_config_dword(root, aer + PCI_ERR_ROOT_COMMAND, ®32);
+ reg32 |= ROOT_PORT_INTR_ON_MESG_MASK;
+- pci_write_config_dword(dev, aer + PCI_ERR_ROOT_COMMAND, reg32);
++ pci_write_config_dword(root, aer + PCI_ERR_ROOT_COMMAND, reg32);
+ }
+
+ return rc ? PCI_ERS_RESULT_DISCONNECT : PCI_ERS_RESULT_RECOVERED;
+@@ -1393,7 +1417,7 @@ static pci_ers_result_t aer_root_reset(struct pci_dev *dev)
+
+ static struct pcie_port_service_driver aerdriver = {
+ .name = "aer",
+- .port_type = PCI_EXP_TYPE_ROOT_PORT,
++ .port_type = PCIE_ANY_PORT,
+ .service = PCIE_PORT_SERVICE_AER,
+
+ .probe = aer_probe,
+diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
+index 8b53aecdb43d..d89d7ed70768 100644
+--- a/drivers/pci/pcie/err.c
++++ b/drivers/pci/pcie/err.c
+@@ -148,13 +148,16 @@ static int report_resume(struct pci_dev *dev, void *data)
+
+ /**
+ * pci_walk_bridge - walk bridges potentially AER affected
+- * @bridge: bridge which may be a Port
++ * @bridge: bridge which may be a Port or an RCEC
+ * @cb: callback to be called for each device found
+ * @userdata: arbitrary pointer to be passed to callback
+ *
+ * If the device provided is a bridge, walk the subordinate bus, including
+ * any bridged devices on buses under this bus. Call the provided callback
+ * on each device found.
++ *
++ * If the device provided has no subordinate bus, e.g., an RCEC, call the
++ * callback on the device itself.
+ */
+ static void pci_walk_bridge(struct pci_dev *bridge,
+ int (*cb)(struct pci_dev *, void *),
+@@ -162,6 +165,8 @@ static void pci_walk_bridge(struct pci_dev *bridge,
+ {
+ if (bridge->subordinate)
+ pci_walk_bus(bridge->subordinate, cb, userdata);
++ else
++ cb(bridge, userdata);
+ }
+
+ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+@@ -173,11 +178,17 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
+
+ /*
+- * Error recovery runs on all subordinates of the bridge. If the
+- * bridge detected the error, it is cleared at the end.
++ * If the error was detected by a Root Port, Downstream Port, or
++ * RCEC, recovery runs on the device itself. For Ports, that also
++ * includes any subordinate devices.
++ *
++ * If it was detected by another device (Endpoint, etc), recovery
++ * runs on the device and anything else under the same Port, i.e.,
++ * everything under "bridge".
+ */
+ if (type == PCI_EXP_TYPE_ROOT_PORT ||
+- type == PCI_EXP_TYPE_DOWNSTREAM)
++ type == PCI_EXP_TYPE_DOWNSTREAM ||
++ type == PCI_EXP_TYPE_RC_EC)
+ bridge = dev;
+ else
+ bridge = pci_upstream_bridge(dev);
+--
+2.35.1
+
--- /dev/null
+From 8036296ea80faabd44f5ca956698e03c023032be Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Nov 2020 16:10:25 -0800
+Subject: PCI/ERR: Rename reset_link() to reset_subordinates()
+
+From: Sean V Kelley <sean.v.kelley@intel.com>
+
+[ Upstream commit 8f1bbfbc3596d401b60d1562b27ec28c2724f60d ]
+
+reset_link() appears to be misnamed. The point is to reset any devices
+below a given bridge, so rename it to reset_subordinates() to make it clear
+that we are passing a bridge with the intent to reset the devices below it.
+
+Link: https://lore.kernel.org/r/20201121001036.8560-5-sean.v.kelley@intel.com
+Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # non-native/no RCEC
+Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pci.h | 4 ++--
+ drivers/pci/pcie/err.c | 8 ++++----
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
+index 4084764bf0b1..0039460c6ab0 100644
+--- a/drivers/pci/pci.h
++++ b/drivers/pci/pci.h
+@@ -559,8 +559,8 @@ static inline int pci_dev_specific_disable_acs_redir(struct pci_dev *dev)
+
+ /* PCI error reporting and recovery */
+ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+- pci_channel_state_t state,
+- pci_ers_result_t (*reset_link)(struct pci_dev *pdev));
++ pci_channel_state_t state,
++ pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev));
+
+ bool pcie_wait_for_link(struct pci_dev *pdev, bool active);
+ #ifdef CONFIG_PCIEASPM
+diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
+index c543f419d8f9..db149c6ce4fb 100644
+--- a/drivers/pci/pcie/err.c
++++ b/drivers/pci/pcie/err.c
+@@ -147,8 +147,8 @@ static int report_resume(struct pci_dev *dev, void *data)
+ }
+
+ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+- pci_channel_state_t state,
+- pci_ers_result_t (*reset_link)(struct pci_dev *pdev))
++ pci_channel_state_t state,
++ pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev))
+ {
+ pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
+ struct pci_bus *bus;
+@@ -165,9 +165,9 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ pci_dbg(dev, "broadcast error_detected message\n");
+ if (state == pci_channel_io_frozen) {
+ pci_walk_bus(bus, report_frozen_detected, &status);
+- status = reset_link(dev);
++ status = reset_subordinates(dev);
+ if (status != PCI_ERS_RESULT_RECOVERED) {
+- pci_warn(dev, "link reset failed\n");
++ pci_warn(dev, "subordinate device reset failed\n");
+ goto failed;
+ }
+ } else {
+--
+2.35.1
+
--- /dev/null
+From b2970f93e386bf38061039b13f071faff2a0c95e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Nov 2020 16:10:27 -0800
+Subject: PCI/ERR: Simplify by computing pci_pcie_type() once
+
+From: Sean V Kelley <sean.v.kelley@intel.com>
+
+[ Upstream commit 480ef7cb9fcebda7b28cbed4f6cdcf0a02f4a6ca ]
+
+Instead of calling pci_pcie_type(dev) twice, call it once and save the
+result. No functional change intended.
+
+Link: https://lore.kernel.org/r/20201121001036.8560-7-sean.v.kelley@intel.com
+Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # non-native/no RCEC
+Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/aer.c | 5 +++--
+ drivers/pci/pcie/err.c | 5 +++--
+ drivers/pci/pcie/portdrv_pci.c | 9 +++++----
+ 3 files changed, 11 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/pci/pcie/aer.c b/drivers/pci/pcie/aer.c
+index 61f78b20b0cf..72dbc193a25f 100644
+--- a/drivers/pci/pcie/aer.c
++++ b/drivers/pci/pcie/aer.c
+@@ -1039,6 +1039,7 @@ EXPORT_SYMBOL_GPL(aer_recover_queue);
+ */
+ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
+ {
++ int type = pci_pcie_type(dev);
+ int aer = dev->aer_cap;
+ int temp;
+
+@@ -1057,8 +1058,8 @@ int aer_get_device_error_info(struct pci_dev *dev, struct aer_err_info *info)
+ &info->mask);
+ if (!(info->status & ~info->mask))
+ return 0;
+- } else if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
+- pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM ||
++ } else if (type == PCI_EXP_TYPE_ROOT_PORT ||
++ type == PCI_EXP_TYPE_DOWNSTREAM ||
+ info->severity == AER_NONFATAL) {
+
+ /* Link is still healthy for IO reads */
+diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
+index 05f61da5ed9d..7a5af873d8bc 100644
+--- a/drivers/pci/pcie/err.c
++++ b/drivers/pci/pcie/err.c
+@@ -150,6 +150,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ pci_channel_state_t state,
+ pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev))
+ {
++ int type = pci_pcie_type(dev);
+ pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
+ struct pci_bus *bus;
+
+@@ -157,8 +158,8 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ * Error recovery runs on all subordinates of the first downstream port.
+ * If the downstream port detected the error, it is cleared at the end.
+ */
+- if (!(pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
+- pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM))
++ if (!(type == PCI_EXP_TYPE_ROOT_PORT ||
++ type == PCI_EXP_TYPE_DOWNSTREAM))
+ dev = pci_upstream_bridge(dev);
+ bus = dev->subordinate;
+
+diff --git a/drivers/pci/pcie/portdrv_pci.c b/drivers/pci/pcie/portdrv_pci.c
+index 26259630fd10..aac1a6828b4f 100644
+--- a/drivers/pci/pcie/portdrv_pci.c
++++ b/drivers/pci/pcie/portdrv_pci.c
+@@ -101,13 +101,14 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
+ static int pcie_portdrv_probe(struct pci_dev *dev,
+ const struct pci_device_id *id)
+ {
++ int type = pci_pcie_type(dev);
+ int status;
+
+ if (!pci_is_pcie(dev) ||
+- ((pci_pcie_type(dev) != PCI_EXP_TYPE_ROOT_PORT) &&
+- (pci_pcie_type(dev) != PCI_EXP_TYPE_UPSTREAM) &&
+- (pci_pcie_type(dev) != PCI_EXP_TYPE_DOWNSTREAM) &&
+- (pci_pcie_type(dev) != PCI_EXP_TYPE_RC_EC)))
++ ((type != PCI_EXP_TYPE_ROOT_PORT) &&
++ (type != PCI_EXP_TYPE_UPSTREAM) &&
++ (type != PCI_EXP_TYPE_DOWNSTREAM) &&
++ (type != PCI_EXP_TYPE_RC_EC)))
+ return -ENODEV;
+
+ status = pcie_port_device_register(dev);
+--
+2.35.1
+
--- /dev/null
+From ddc22bfa8c54475044afc1a76a16e64d6e760dc4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Nov 2020 16:10:26 -0800
+Subject: PCI/ERR: Simplify by using pci_upstream_bridge()
+
+From: Sean V Kelley <sean.v.kelley@intel.com>
+
+[ Upstream commit 5d69dcc9f839bd2d5cac7a098712f52149e1673f ]
+
+Use pci_upstream_bridge() in place of dev->bus->self. No functional change
+intended.
+
+Link: https://lore.kernel.org/r/20201121001036.8560-6-sean.v.kelley@intel.com
+Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # non-native/no RCEC
+Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/err.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
+index db149c6ce4fb..05f61da5ed9d 100644
+--- a/drivers/pci/pcie/err.c
++++ b/drivers/pci/pcie/err.c
+@@ -159,7 +159,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ */
+ if (!(pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT ||
+ pci_pcie_type(dev) == PCI_EXP_TYPE_DOWNSTREAM))
+- dev = dev->bus->self;
++ dev = pci_upstream_bridge(dev);
+ bus = dev->subordinate;
+
+ pci_dbg(dev, "broadcast error_detected message\n");
+--
+2.35.1
+
--- /dev/null
+From f5c070bfce8e77823526d3e3e073ba687191d0ae Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 20 Nov 2020 16:10:28 -0800
+Subject: PCI/ERR: Use "bridge" for clarity in pcie_do_recovery()
+
+From: Sean V Kelley <sean.v.kelley@intel.com>
+
+[ Upstream commit 0791721d800790e6e533bd8467df67f0dc4f2fec ]
+
+pcie_do_recovery() may be called with "dev" being either a bridge (Root
+Port or Switch Downstream Port) or an Endpoint. The bulk of the function
+deals with the bridge, so if we start with an Endpoint, we reset "dev" to
+be the bridge leading to it.
+
+For clarity, replace "dev" in the body of the function with "bridge". No
+functional change intended.
+
+Link: https://lore.kernel.org/r/20201121001036.8560-8-sean.v.kelley@intel.com
+Tested-by: Jonathan Cameron <Jonathan.Cameron@huawei.com> # non-native/no RCEC
+Signed-off-by: Sean V Kelley <sean.v.kelley@intel.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
+Acked-by: Jonathan Cameron <Jonathan.Cameron@huawei.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/pci/pcie/err.c | 37 ++++++++++++++++++++-----------------
+ 1 file changed, 20 insertions(+), 17 deletions(-)
+
+diff --git a/drivers/pci/pcie/err.c b/drivers/pci/pcie/err.c
+index 7a5af873d8bc..46a5b84f8842 100644
+--- a/drivers/pci/pcie/err.c
++++ b/drivers/pci/pcie/err.c
+@@ -151,24 +151,27 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ pci_ers_result_t (*reset_subordinates)(struct pci_dev *pdev))
+ {
+ int type = pci_pcie_type(dev);
+- pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
++ struct pci_dev *bridge;
+ struct pci_bus *bus;
++ pci_ers_result_t status = PCI_ERS_RESULT_CAN_RECOVER;
+
+ /*
+- * Error recovery runs on all subordinates of the first downstream port.
+- * If the downstream port detected the error, it is cleared at the end.
++ * Error recovery runs on all subordinates of the bridge. If the
++ * bridge detected the error, it is cleared at the end.
+ */
+ if (!(type == PCI_EXP_TYPE_ROOT_PORT ||
+ type == PCI_EXP_TYPE_DOWNSTREAM))
+- dev = pci_upstream_bridge(dev);
+- bus = dev->subordinate;
++ bridge = pci_upstream_bridge(dev);
++ else
++ bridge = dev;
+
+- pci_dbg(dev, "broadcast error_detected message\n");
++ bus = bridge->subordinate;
++ pci_dbg(bridge, "broadcast error_detected message\n");
+ if (state == pci_channel_io_frozen) {
+ pci_walk_bus(bus, report_frozen_detected, &status);
+- status = reset_subordinates(dev);
++ status = reset_subordinates(bridge);
+ if (status != PCI_ERS_RESULT_RECOVERED) {
+- pci_warn(dev, "subordinate device reset failed\n");
++ pci_warn(bridge, "subordinate device reset failed\n");
+ goto failed;
+ }
+ } else {
+@@ -177,7 +180,7 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+
+ if (status == PCI_ERS_RESULT_CAN_RECOVER) {
+ status = PCI_ERS_RESULT_RECOVERED;
+- pci_dbg(dev, "broadcast mmio_enabled message\n");
++ pci_dbg(bridge, "broadcast mmio_enabled message\n");
+ pci_walk_bus(bus, report_mmio_enabled, &status);
+ }
+
+@@ -188,27 +191,27 @@ pci_ers_result_t pcie_do_recovery(struct pci_dev *dev,
+ * drivers' slot_reset callbacks?
+ */
+ status = PCI_ERS_RESULT_RECOVERED;
+- pci_dbg(dev, "broadcast slot_reset message\n");
++ pci_dbg(bridge, "broadcast slot_reset message\n");
+ pci_walk_bus(bus, report_slot_reset, &status);
+ }
+
+ if (status != PCI_ERS_RESULT_RECOVERED)
+ goto failed;
+
+- pci_dbg(dev, "broadcast resume message\n");
++ pci_dbg(bridge, "broadcast resume message\n");
+ pci_walk_bus(bus, report_resume, &status);
+
+- if (pcie_aer_is_native(dev))
+- pcie_clear_device_status(dev);
+- pci_aer_clear_nonfatal_status(dev);
+- pci_info(dev, "device recovery successful\n");
++ if (pcie_aer_is_native(bridge))
++ pcie_clear_device_status(bridge);
++ pci_aer_clear_nonfatal_status(bridge);
++ pci_info(bridge, "device recovery successful\n");
+ return status;
+
+ failed:
+- pci_uevent_ers(dev, PCI_ERS_RESULT_DISCONNECT);
++ pci_uevent_ers(bridge, PCI_ERS_RESULT_DISCONNECT);
+
+ /* TODO: Should kernel panic here? */
+- pci_info(dev, "device recovery failed\n");
++ pci_info(bridge, "device recovery failed\n");
+
+ return status;
+ }
+--
+2.35.1
+
--- /dev/null
+From 63536db5817afe3bf26cc8827f2899fb225cf374 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 28 Jul 2022 00:32:18 +1000
+Subject: powerpc/powernv/kvm: Use darn for H_RANDOM on Power9
+
+From: Jason A. Donenfeld <Jason@zx2c4.com>
+
+[ Upstream commit 7ef3d06f1bc4a5e62273726f3dc2bd258ae1c71f ]
+
+The existing logic in KVM to support guests calling H_RANDOM only works
+on Power8, because it looks for an RNG in the device tree, but on Power9
+we just use darn.
+
+In addition the existing code needs to work in real mode, so we have the
+special cased powernv_get_random_real_mode() to deal with that.
+
+Instead just have KVM call ppc_md.get_random_seed(), and do the real
+mode check inside of there, that way we use whatever RNG is available,
+including darn on Power9.
+
+Fixes: e928e9cb3601 ("KVM: PPC: Book3S HV: Add fast real-mode H_RANDOM implementation.")
+Cc: stable@vger.kernel.org # v4.1+
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Tested-by: Sachin Sant <sachinp@linux.ibm.com>
+[mpe: Rebase on previous commit, update change log appropriately]
+Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
+Link: https://lore.kernel.org/r/20220727143219.2684192-2-mpe@ellerman.id.au
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/powerpc/include/asm/archrandom.h | 5 ----
+ arch/powerpc/kvm/book3s_hv_builtin.c | 7 +++---
+ arch/powerpc/platforms/powernv/rng.c | 36 ++++++---------------------
+ 3 files changed, 12 insertions(+), 36 deletions(-)
+
+diff --git a/arch/powerpc/include/asm/archrandom.h b/arch/powerpc/include/asm/archrandom.h
+index 9a53e29680f4..258174304904 100644
+--- a/arch/powerpc/include/asm/archrandom.h
++++ b/arch/powerpc/include/asm/archrandom.h
+@@ -38,12 +38,7 @@ static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
+ #endif /* CONFIG_ARCH_RANDOM */
+
+ #ifdef CONFIG_PPC_POWERNV
+-int powernv_hwrng_present(void);
+ int powernv_get_random_long(unsigned long *v);
+-int powernv_get_random_real_mode(unsigned long *v);
+-#else
+-static inline int powernv_hwrng_present(void) { return 0; }
+-static inline int powernv_get_random_real_mode(unsigned long *v) { return 0; }
+ #endif
+
+ #endif /* _ASM_POWERPC_ARCHRANDOM_H */
+diff --git a/arch/powerpc/kvm/book3s_hv_builtin.c b/arch/powerpc/kvm/book3s_hv_builtin.c
+index 856a04ca833c..2f3e8b547f4e 100644
+--- a/arch/powerpc/kvm/book3s_hv_builtin.c
++++ b/arch/powerpc/kvm/book3s_hv_builtin.c
+@@ -19,7 +19,7 @@
+ #include <asm/cputable.h>
+ #include <asm/kvm_ppc.h>
+ #include <asm/kvm_book3s.h>
+-#include <asm/archrandom.h>
++#include <asm/machdep.h>
+ #include <asm/xics.h>
+ #include <asm/xive.h>
+ #include <asm/dbell.h>
+@@ -176,13 +176,14 @@ EXPORT_SYMBOL_GPL(kvmppc_hcall_impl_hv_realmode);
+
+ int kvmppc_hwrng_present(void)
+ {
+- return powernv_hwrng_present();
++ return ppc_md.get_random_seed != NULL;
+ }
+ EXPORT_SYMBOL_GPL(kvmppc_hwrng_present);
+
+ long kvmppc_rm_h_random(struct kvm_vcpu *vcpu)
+ {
+- if (powernv_get_random_real_mode(&vcpu->arch.regs.gpr[4]))
++ if (ppc_md.get_random_seed &&
++ ppc_md.get_random_seed(&vcpu->arch.regs.gpr[4]))
+ return H_SUCCESS;
+
+ return H_HARDWARE;
+diff --git a/arch/powerpc/platforms/powernv/rng.c b/arch/powerpc/platforms/powernv/rng.c
+index a99033c3dce7..5f81ff9b5265 100644
+--- a/arch/powerpc/platforms/powernv/rng.c
++++ b/arch/powerpc/platforms/powernv/rng.c
+@@ -29,15 +29,6 @@ struct powernv_rng {
+
+ static DEFINE_PER_CPU(struct powernv_rng *, powernv_rng);
+
+-int powernv_hwrng_present(void)
+-{
+- struct powernv_rng *rng;
+-
+- rng = get_cpu_var(powernv_rng);
+- put_cpu_var(rng);
+- return rng != NULL;
+-}
+-
+ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
+ {
+ unsigned long parity;
+@@ -58,19 +49,6 @@ static unsigned long rng_whiten(struct powernv_rng *rng, unsigned long val)
+ return val;
+ }
+
+-int powernv_get_random_real_mode(unsigned long *v)
+-{
+- struct powernv_rng *rng;
+-
+- rng = raw_cpu_read(powernv_rng);
+- if (!rng)
+- return 0;
+-
+- *v = rng_whiten(rng, __raw_rm_readq(rng->regs_real));
+-
+- return 1;
+-}
+-
+ static int powernv_get_random_darn(unsigned long *v)
+ {
+ unsigned long val;
+@@ -107,12 +85,14 @@ int powernv_get_random_long(unsigned long *v)
+ {
+ struct powernv_rng *rng;
+
+- rng = get_cpu_var(powernv_rng);
+-
+- *v = rng_whiten(rng, in_be64(rng->regs));
+-
+- put_cpu_var(rng);
+-
++ if (mfmsr() & MSR_DR) {
++ rng = get_cpu_var(powernv_rng);
++ *v = rng_whiten(rng, in_be64(rng->regs));
++ put_cpu_var(rng);
++ } else {
++ rng = raw_cpu_read(powernv_rng);
++ *v = rng_whiten(rng, __raw_rm_readq(rng->regs_real));
++ }
+ return 1;
+ }
+ EXPORT_SYMBOL_GPL(powernv_get_random_long);
+--
+2.35.1
+
--- /dev/null
+From d362b6cb989afd1038bad554903e8b88218a2930 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 22:20:42 -0700
+Subject: scsi: qla2xxx: Fix discovery issues in FC-AL topology
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit 47ccb113cead905bdc236571bf8ac6fed90321b3 ]
+
+A direct attach tape device, when gets swapped with another, was not
+discovered. Fix this by looking at loop map and reinitialize link if there
+are devices present.
+
+Link: https://lore.kernel.org/linux-scsi/baef87c3-5dad-3b47-44c1-6914bfc90108@cybernetics.com/
+Link: https://lore.kernel.org/r/20220713052045.10683-8-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Reported-by: Tony Battersby <tonyb@cybernetics.com>
+Tested-by: Tony Battersby <tonyb@cybernetics.com>
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_gbl.h | 3 ++-
+ drivers/scsi/qla2xxx/qla_init.c | 29 +++++++++++++++++++++++++++++
+ drivers/scsi/qla2xxx/qla_mbx.c | 5 ++++-
+ 3 files changed, 35 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_gbl.h b/drivers/scsi/qla2xxx/qla_gbl.h
+index 3bc185027342..7e5ee31581d6 100644
+--- a/drivers/scsi/qla2xxx/qla_gbl.h
++++ b/drivers/scsi/qla2xxx/qla_gbl.h
+@@ -405,7 +405,8 @@ extern int
+ qla2x00_get_resource_cnts(scsi_qla_host_t *);
+
+ extern int
+-qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map);
++qla2x00_get_fcal_position_map(scsi_qla_host_t *ha, char *pos_map,
++ u8 *num_entries);
+
+ extern int
+ qla2x00_get_link_status(scsi_qla_host_t *, uint16_t, struct link_statistics *,
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index 1618b4a9c75e..422ff67038d1 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -5274,6 +5274,22 @@ static int qla2x00_configure_n2n_loop(scsi_qla_host_t *vha)
+ return QLA_FUNCTION_FAILED;
+ }
+
++static void
++qla_reinitialize_link(scsi_qla_host_t *vha)
++{
++ int rval;
++
++ atomic_set(&vha->loop_state, LOOP_DOWN);
++ atomic_set(&vha->loop_down_timer, LOOP_DOWN_TIME);
++ rval = qla2x00_full_login_lip(vha);
++ if (rval == QLA_SUCCESS) {
++ ql_dbg(ql_dbg_disc, vha, 0xd050, "Link reinitialized\n");
++ } else {
++ ql_dbg(ql_dbg_disc, vha, 0xd051,
++ "Link reinitialization failed (%d)\n", rval);
++ }
++}
++
+ /*
+ * qla2x00_configure_local_loop
+ * Updates Fibre Channel Device Database with local loop devices.
+@@ -5325,6 +5341,19 @@ qla2x00_configure_local_loop(scsi_qla_host_t *vha)
+ spin_unlock_irqrestore(&vha->work_lock, flags);
+
+ if (vha->scan.scan_retry < MAX_SCAN_RETRIES) {
++ u8 loop_map_entries = 0;
++ int rc;
++
++ rc = qla2x00_get_fcal_position_map(vha, NULL,
++ &loop_map_entries);
++ if (rc == QLA_SUCCESS && loop_map_entries > 1) {
++ /*
++ * There are devices that are still not logged
++ * in. Reinitialize to give them a chance.
++ */
++ qla_reinitialize_link(vha);
++ return QLA_FUNCTION_FAILED;
++ }
+ set_bit(LOCAL_LOOP_UPDATE, &vha->dpc_flags);
+ set_bit(LOOP_RESYNC_NEEDED, &vha->dpc_flags);
+ }
+diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
+index bd5bca71ddd3..6ff720d8961d 100644
+--- a/drivers/scsi/qla2xxx/qla_mbx.c
++++ b/drivers/scsi/qla2xxx/qla_mbx.c
+@@ -3017,7 +3017,8 @@ qla2x00_get_resource_cnts(scsi_qla_host_t *vha)
+ * Kernel context.
+ */
+ int
+-qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
++qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map,
++ u8 *num_entries)
+ {
+ int rval;
+ mbx_cmd_t mc;
+@@ -3057,6 +3058,8 @@ qla2x00_get_fcal_position_map(scsi_qla_host_t *vha, char *pos_map)
+
+ if (pos_map)
+ memcpy(pos_map, pmap, FCAL_MAP_SIZE);
++ if (num_entries)
++ *num_entries = pmap[0];
+ }
+ dma_pool_free(ha->s_dma_pool, pmap, pmap_dma);
+
+--
+2.35.1
+
--- /dev/null
+From 21ad6a9ed8b62c19a7f873d4f2d95703ce908796 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:07 -0700
+Subject: scsi: qla2xxx: Fix erroneous mailbox timeout after PCI error
+ injection
+
+From: Quinn Tran <qutran@marvell.com>
+
+[ Upstream commit f260694e6463b63ae550aad25ddefe94cb1904da ]
+
+Clear wait for mailbox interrupt flag to prevent stale mailbox:
+
+Feb 22 05:22:56 ltcden4-lp7 kernel: qla2xxx [0135:90:00.1]-500a:4: LOOP UP detected (16 Gbps).
+Feb 22 05:22:59 ltcden4-lp7 kernel: qla2xxx [0135:90:00.1]-d04c:4: MBX Command timeout for cmd 69, ...
+
+To fix the issue, driver needs to clear the MBX_INTR_WAIT flag on purging
+the mailbox. When the stale mailbox completion does arrive, it will be
+dropped.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-11-njavali@marvell.com
+Fixes: b6faaaf796d7 ("scsi: qla2xxx: Serialize mailbox request")
+Cc: Naresh Bannoth <nbannoth@in.ibm.com>
+Cc: Kyle Mahlkuch <Kyle.Mahlkuch@ibm.com>
+Cc: stable@vger.kernel.org
+Reported-by: Naresh Bannoth <nbannoth@in.ibm.com>
+Tested-by: Naresh Bannoth <nbannoth@in.ibm.com>
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_mbx.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_mbx.c b/drivers/scsi/qla2xxx/qla_mbx.c
+index fe702ac5ce41..bd5bca71ddd3 100644
+--- a/drivers/scsi/qla2xxx/qla_mbx.c
++++ b/drivers/scsi/qla2xxx/qla_mbx.c
+@@ -271,6 +271,12 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
+ atomic_inc(&ha->num_pend_mbx_stage3);
+ if (!wait_for_completion_timeout(&ha->mbx_intr_comp,
+ mcp->tov * HZ)) {
++ ql_dbg(ql_dbg_mbx, vha, 0x117a,
++ "cmd=%x Timeout.\n", command);
++ spin_lock_irqsave(&ha->hardware_lock, flags);
++ clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
++ spin_unlock_irqrestore(&ha->hardware_lock, flags);
++
+ if (chip_reset != ha->chip_reset) {
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+ ha->flags.mbox_busy = 0;
+@@ -281,12 +287,6 @@ qla2x00_mailbox_command(scsi_qla_host_t *vha, mbx_cmd_t *mcp)
+ rval = QLA_ABORTED;
+ goto premature_exit;
+ }
+- ql_dbg(ql_dbg_mbx, vha, 0x117a,
+- "cmd=%x Timeout.\n", command);
+- spin_lock_irqsave(&ha->hardware_lock, flags);
+- clear_bit(MBX_INTR_WAIT, &ha->mbx_cmd_flags);
+- spin_unlock_irqrestore(&ha->hardware_lock, flags);
+-
+ } else if (ha->flags.purge_mbox ||
+ chip_reset != ha->chip_reset) {
+ spin_lock_irqsave(&ha->hardware_lock, flags);
+--
+2.35.1
+
--- /dev/null
+From feaeef46da9304a6e31462a9473dcdd1695b4784 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:03 -0700
+Subject: scsi: qla2xxx: Fix losing FCP-2 targets during port perturbation
+ tests
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit 58d1c124cd79ea686b512043c5bd515590b2ed95 ]
+
+When a mix of FCP-2 (tape) and non-FCP-2 targets are present, FCP-2 target
+state was incorrectly transitioned when both of the targets were gone. Fix
+this by ignoring state transition for FCP-2 targets.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-7-njavali@marvell.com
+Fixes: 44c57f205876 ("scsi: qla2xxx: Changes to support FCP2 Target")
+Cc: stable@vger.kernel.org
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_gs.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
+index c768c14d6b35..20bbd69e35e5 100644
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -3552,7 +3552,7 @@ void qla24xx_async_gnnft_done(scsi_qla_host_t *vha, srb_t *sp)
+ do_delete) {
+ if (fcport->loop_id != FC_NO_LOOP_ID) {
+ if (fcport->flags & FCF_FCP2_DEVICE)
+- fcport->logout_on_delete = 0;
++ continue;
+
+ ql_dbg(ql_dbg_disc, vha, 0x20f0,
+ "%s %d %8phC post del sess\n",
+--
+2.35.1
+
--- /dev/null
+From da944a2da949880d6c80e5bbd7ab141b13c19844 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:06 -0700
+Subject: scsi: qla2xxx: Fix losing FCP-2 targets on long port disable with
+ I/Os
+
+From: Arun Easi <aeasi@marvell.com>
+
+[ Upstream commit 2416ccd3815ba1613e10a6da0a24ef21acfe5633 ]
+
+FCP-2 devices were not coming back online once they were lost, login
+retries exhausted, and then came back up. Fix this by accepting RSCN when
+the device is not online.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-10-njavali@marvell.com
+Fixes: 44c57f205876 ("scsi: qla2xxx: Changes to support FCP2 Target")
+Cc: stable@vger.kernel.org
+Signed-off-by: Arun Easi <aeasi@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_init.c | 12 ++++++++----
+ 1 file changed, 8 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_init.c b/drivers/scsi/qla2xxx/qla_init.c
+index 08c72d3aeaa9..1618b4a9c75e 100644
+--- a/drivers/scsi/qla2xxx/qla_init.c
++++ b/drivers/scsi/qla2xxx/qla_init.c
+@@ -1734,7 +1734,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+ case RSCN_PORT_ADDR:
+ fcport = qla2x00_find_fcport_by_nportid(vha, &ea->id, 1);
+ if (fcport) {
+- if (fcport->flags & FCF_FCP2_DEVICE) {
++ if (fcport->flags & FCF_FCP2_DEVICE &&
++ atomic_read(&fcport->state) == FCS_ONLINE) {
+ ql_dbg(ql_dbg_disc, vha, 0x2115,
+ "Delaying session delete for FCP2 portid=%06x %8phC ",
+ fcport->d_id.b24, fcport->port_name);
+@@ -1746,7 +1747,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+ break;
+ case RSCN_AREA_ADDR:
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+- if (fcport->flags & FCF_FCP2_DEVICE)
++ if (fcport->flags & FCF_FCP2_DEVICE &&
++ atomic_read(&fcport->state) == FCS_ONLINE)
+ continue;
+
+ if ((ea->id.b24 & 0xffff00) == (fcport->d_id.b24 & 0xffff00)) {
+@@ -1757,7 +1759,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+ break;
+ case RSCN_DOM_ADDR:
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+- if (fcport->flags & FCF_FCP2_DEVICE)
++ if (fcport->flags & FCF_FCP2_DEVICE &&
++ atomic_read(&fcport->state) == FCS_ONLINE)
+ continue;
+
+ if ((ea->id.b24 & 0xff0000) == (fcport->d_id.b24 & 0xff0000)) {
+@@ -1769,7 +1772,8 @@ void qla2x00_handle_rscn(scsi_qla_host_t *vha, struct event_arg *ea)
+ case RSCN_FAB_ADDR:
+ default:
+ list_for_each_entry(fcport, &vha->vp_fcports, list) {
+- if (fcport->flags & FCF_FCP2_DEVICE)
++ if (fcport->flags & FCF_FCP2_DEVICE &&
++ atomic_read(&fcport->state) == FCS_ONLINE)
+ continue;
+
+ fcport->scan_needed = 1;
+--
+2.35.1
+
--- /dev/null
+From d6f05f982fde7238118f8c123cc9b2247d14dc6d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 15 Jun 2022 22:35:01 -0700
+Subject: scsi: qla2xxx: Turn off multi-queue for 8G adapters
+
+From: Quinn Tran <qutran@marvell.com>
+
+[ Upstream commit 5304673bdb1635e27555bd636fd5d6956f1cd552 ]
+
+For 8G adapters, multi-queue was enabled accidentally. Make sure
+multi-queue is not enabled.
+
+Link: https://lore.kernel.org/r/20220616053508.27186-5-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Signed-off-by: Quinn Tran <qutran@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_def.h | 4 ++--
+ drivers/scsi/qla2xxx/qla_isr.c | 16 ++++++----------
+ 2 files changed, 8 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index 15eeeef4562b..6afce455b9d8 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -4135,8 +4135,8 @@ struct qla_hw_data {
+ #define IS_OEM_001(ha) ((ha)->device_type & DT_OEM_001)
+ #define HAS_EXTENDED_IDS(ha) ((ha)->device_type & DT_EXTENDED_IDS)
+ #define IS_CT6_SUPPORTED(ha) ((ha)->device_type & DT_CT6_SUPPORTED)
+-#define IS_MQUE_CAPABLE(ha) ((ha)->mqenable || IS_QLA83XX(ha) || \
+- IS_QLA27XX(ha) || IS_QLA28XX(ha))
++#define IS_MQUE_CAPABLE(ha) (IS_QLA83XX(ha) || IS_QLA27XX(ha) || \
++ IS_QLA28XX(ha))
+ #define IS_BIDI_CAPABLE(ha) \
+ (IS_QLA25XX(ha) || IS_QLA2031(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha))
+ /* Bit 21 of fw_attributes decides the MCTP capabilities */
+diff --git a/drivers/scsi/qla2xxx/qla_isr.c b/drivers/scsi/qla2xxx/qla_isr.c
+index 6106f93aa32f..7ea73ad845de 100644
+--- a/drivers/scsi/qla2xxx/qla_isr.c
++++ b/drivers/scsi/qla2xxx/qla_isr.c
+@@ -4054,16 +4054,12 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
+ }
+
+ /* Enable MSI-X vector for response queue update for queue 0 */
+- if (IS_QLA83XX(ha) || IS_QLA27XX(ha) || IS_QLA28XX(ha)) {
+- if (ha->msixbase && ha->mqiobase &&
+- (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
+- ql2xmqsupport))
+- ha->mqenable = 1;
+- } else
+- if (ha->mqiobase &&
+- (ha->max_rsp_queues > 1 || ha->max_req_queues > 1 ||
+- ql2xmqsupport))
+- ha->mqenable = 1;
++ if (IS_MQUE_CAPABLE(ha) &&
++ (ha->msixbase && ha->mqiobase && ha->max_qpairs))
++ ha->mqenable = 1;
++ else
++ ha->mqenable = 0;
++
+ ql_dbg(ql_dbg_multiq, vha, 0xc005,
+ "mqiobase=%p, max_rsp_queues=%d, max_req_queues=%d.\n",
+ ha->mqiobase, ha->max_rsp_queues, ha->max_req_queues);
+--
+2.35.1
+
--- /dev/null
+From 600a0835f7d06c3ccc8533f3df0f5d130fbddbc2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 12 Jul 2022 22:20:44 -0700
+Subject: scsi: qla2xxx: Update manufacturer details
+
+From: Bikash Hazarika <bhazarika@marvell.com>
+
+[ Upstream commit 1ccad27716ecad1fd58c35e579bedb81fa5e1ad5 ]
+
+Update manufacturer details to indicate Marvell Semiconductors.
+
+Link: https://lore.kernel.org/r/20220713052045.10683-10-njavali@marvell.com
+Cc: stable@vger.kernel.org
+Reviewed-by: Himanshu Madhani <himanshu.madhani@oracle.com>
+Signed-off-by: Bikash Hazarika <bhazarika@marvell.com>
+Signed-off-by: Nilesh Javali <njavali@marvell.com>
+Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/scsi/qla2xxx/qla_def.h | 2 +-
+ drivers/scsi/qla2xxx/qla_gs.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/scsi/qla2xxx/qla_def.h b/drivers/scsi/qla2xxx/qla_def.h
+index 6afce455b9d8..44f80412a0a4 100644
+--- a/drivers/scsi/qla2xxx/qla_def.h
++++ b/drivers/scsi/qla2xxx/qla_def.h
+@@ -56,7 +56,7 @@ typedef struct {
+ #include "qla_nvme.h"
+ #define QLA2XXX_DRIVER_NAME "qla2xxx"
+ #define QLA2XXX_APIDEV "ql2xapidev"
+-#define QLA2XXX_MANUFACTURER "QLogic Corporation"
++#define QLA2XXX_MANUFACTURER "Marvell Semiconductor, Inc."
+
+ /*
+ * We have MAILBOX_REGISTER_COUNT sized arrays in a few places,
+diff --git a/drivers/scsi/qla2xxx/qla_gs.c b/drivers/scsi/qla2xxx/qla_gs.c
+index 20bbd69e35e5..d9ac17dbad78 100644
+--- a/drivers/scsi/qla2xxx/qla_gs.c
++++ b/drivers/scsi/qla2xxx/qla_gs.c
+@@ -1614,7 +1614,7 @@ qla2x00_hba_attributes(scsi_qla_host_t *vha, void *entries,
+ eiter->type = cpu_to_be16(FDMI_HBA_MANUFACTURER);
+ alen = scnprintf(
+ eiter->a.manufacturer, sizeof(eiter->a.manufacturer),
+- "%s", "QLogic Corporation");
++ "%s", QLA2XXX_MANUFACTURER);
+ alen += FDMI_ATTR_ALIGNMENT(alen);
+ alen += FDMI_ATTR_TYPELEN(eiter);
+ eiter->len = cpu_to_be16(alen);
+--
+2.35.1
+
--- /dev/null
+From efccf7b49e27bce463417667d41f2fbc41ac1ef2 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Jun 2021 20:39:03 +0200
+Subject: serial: 8250: Correct the clock for OxSemi PCIe devices
+
+From: Maciej W. Rozycki <macro@orcam.me.uk>
+
+[ Upstream commit 6cbe45d8ac9316ceedd0749759bd54caf03f7012 ]
+
+Oxford Semiconductor PCIe (Tornado) serial port devices are driven by a
+fixed 62.5MHz clock input derived from the 100MHz PCI Express clock.
+
+In the enhanced (650) mode, which we select in `autoconfig_has_efr' by
+setting the ECB bit in the EFR register, and in the absence of clock
+reconfiguration, which we currently don't do, the clock rate is divided
+only by the oversampling rate of 16 as it is supplied to the baud rate
+generator, yielding the baud base of 3906250. This comes from the reset
+values of the TCR and MCR[7] registers which are both zero[1][2][3][4],
+choosing the oversampling rate of 16 and the normal (divide by 1) baud
+rate generator prescaler respectively. This is the rate that is divided
+by the value held in the divisor latch to determine the baud rate used.
+
+Replace the incorrect baud base of 4000000 with the right value of
+3906250 then.
+
+References:
+
+[1] "OXPCIe200 PCI Express Multi-Port Bridge", Oxford Semiconductor,
+ Inc., DS-0045, 10 Nov 2008, Section "Reset Configuration", p. 72
+
+[2] "OXPCIe952 PCI Express Bridge to Dual Serial & Parallel Port",
+ Oxford Semiconductor, Inc., DS-0046, Mar 06 08, Section "Reset
+ Configuration", p. 27
+
+[3] "OXPCIe954 PCI Express Bridge to Quad Serial Port", Oxford
+ Semiconductor, Inc., DS-0047, Feb 08, Section "Reset Configuration",
+ p. 28
+
+[4] "OXPCIe958 PCI Express Bridge to Octal Serial Port", Oxford
+ Semiconductor, Inc., DS-0048, Feb 08, Section "Reset Configuration",
+ p. 28
+
+Fixes: 7106b4e333bae ("8250: Oxford Semiconductor Devices")
+Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
+Link: https://lore.kernel.org/r/alpine.DEB.2.21.2106100203510.5469@angie.orcam.me.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/8250/8250_pci.c | 128 ++++++++++++++---------------
+ 1 file changed, 64 insertions(+), 64 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index c309a8a31621..bdc262b4109c 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -2862,7 +2862,7 @@ enum pci_board_num_t {
+ pbn_b0_2_1843200,
+ pbn_b0_4_1843200,
+
+- pbn_b0_1_4000000,
++ pbn_b0_1_3906250,
+
+ pbn_b0_bt_1_115200,
+ pbn_b0_bt_2_115200,
+@@ -2942,10 +2942,10 @@ enum pci_board_num_t {
+ pbn_plx_romulus,
+ pbn_endrun_2_3906250,
+ pbn_oxsemi,
+- pbn_oxsemi_1_4000000,
+- pbn_oxsemi_2_4000000,
+- pbn_oxsemi_4_4000000,
+- pbn_oxsemi_8_4000000,
++ pbn_oxsemi_1_3906250,
++ pbn_oxsemi_2_3906250,
++ pbn_oxsemi_4_3906250,
++ pbn_oxsemi_8_3906250,
+ pbn_intel_i960,
+ pbn_sgi_ioc3,
+ pbn_computone_4,
+@@ -3092,10 +3092,10 @@ static struct pciserial_board pci_boards[] = {
+ .uart_offset = 8,
+ },
+
+- [pbn_b0_1_4000000] = {
++ [pbn_b0_1_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+- .base_baud = 4000000,
++ .base_baud = 3906250,
+ .uart_offset = 8,
+ },
+
+@@ -3490,31 +3490,31 @@ static struct pciserial_board pci_boards[] = {
+ .base_baud = 115200,
+ .uart_offset = 8,
+ },
+- [pbn_oxsemi_1_4000000] = {
++ [pbn_oxsemi_1_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 1,
+- .base_baud = 4000000,
++ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+- [pbn_oxsemi_2_4000000] = {
++ [pbn_oxsemi_2_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 2,
+- .base_baud = 4000000,
++ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+- [pbn_oxsemi_4_4000000] = {
++ [pbn_oxsemi_4_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 4,
+- .base_baud = 4000000,
++ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+- [pbn_oxsemi_8_4000000] = {
++ [pbn_oxsemi_8_3906250] = {
+ .flags = FL_BASE0,
+ .num_ports = 8,
+- .base_baud = 4000000,
++ .base_baud = 3906250,
+ .uart_offset = 0x200,
+ .first_offset = 0x1000,
+ },
+@@ -4528,158 +4528,158 @@ static const struct pci_device_id serial_pci_tbl[] = {
+ */
+ { PCI_VENDOR_ID_OXSEMI, 0xc101, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_4000000 },
++ pbn_b0_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc105, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_4000000 },
++ pbn_b0_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc11b, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc11f, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc120, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_4000000 },
++ pbn_b0_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc124, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_4000000 },
++ pbn_b0_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc138, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc13d, /* OXPCIe952 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc140, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_4000000 },
++ pbn_b0_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc141, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_4000000 },
++ pbn_b0_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc144, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_4000000 },
++ pbn_b0_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc145, /* OXPCIe952 1 Legacy UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_b0_1_4000000 },
++ pbn_b0_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc158, /* OXPCIe952 2 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_2_4000000 },
++ pbn_oxsemi_2_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc15d, /* OXPCIe952 2 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_2_4000000 },
++ pbn_oxsemi_2_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc208, /* OXPCIe954 4 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_4_4000000 },
++ pbn_oxsemi_4_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc20d, /* OXPCIe954 4 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_4_4000000 },
++ pbn_oxsemi_4_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc308, /* OXPCIe958 8 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_8_4000000 },
++ pbn_oxsemi_8_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc30d, /* OXPCIe958 8 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_8_4000000 },
++ pbn_oxsemi_8_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc40b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc40f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc41b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc41f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc42b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc42f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc43b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc43f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc44b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc44f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc45b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc45f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc46b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc46f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc47b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc47f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc48b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc48f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc49b, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc49f, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4ab, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4af, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4bb, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4bf, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4cb, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_OXSEMI, 0xc4cf, /* OXPCIe200 1 Native UART */
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ /*
+ * Mainpine Inc. IQ Express "Rev3" utilizing OxSemi Tornado
+ */
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 1 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4001, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_oxsemi_1_3906250 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 2 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4002, 0, 0,
+- pbn_oxsemi_2_4000000 },
++ pbn_oxsemi_2_3906250 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 4 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4004, 0, 0,
+- pbn_oxsemi_4_4000000 },
++ pbn_oxsemi_4_3906250 },
+ { PCI_VENDOR_ID_MAINPINE, 0x4000, /* IQ Express 8 Port V.34 Super-G3 Fax */
+ PCI_VENDOR_ID_MAINPINE, 0x4008, 0, 0,
+- pbn_oxsemi_8_4000000 },
++ pbn_oxsemi_8_3906250 },
+
+ /*
+ * Digi/IBM PCIe 2-port Async EIA-232 Adapter utilizing OxSemi Tornado
+ */
+ { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
+ PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_2_4000000 },
++ pbn_oxsemi_2_3906250 },
+
+ /*
+ * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
+--
+2.35.1
+
--- /dev/null
+From bede9802eef9893d3067aa686dd1dccad3c2e943 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 10 Jun 2021 20:38:59 +0200
+Subject: serial: 8250: Dissociate 4MHz Titan ports from Oxford ports
+
+From: Maciej W. Rozycki <macro@orcam.me.uk>
+
+[ Upstream commit f771a34b141124a68265f91acae34cdb08aeb9e0 ]
+
+Oxford Semiconductor PCIe (Tornado) serial port devices have their baud
+base set incorrectly, however their `pciserial_board' entries have been
+reused for Titan serial port devices. Define own entries for the latter
+devices then, carrying over the settings, so that Oxford entries can be
+fixed.
+
+Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
+Link: https://lore.kernel.org/r/alpine.DEB.2.21.2106100142310.5469@angie.orcam.me.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/8250/8250_pci.c | 44 ++++++++++++++++++++++++++----
+ 1 file changed, 38 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index da2373787f85..c309a8a31621 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -2983,6 +2983,10 @@ enum pci_board_num_t {
+ pbn_sunix_pci_4s,
+ pbn_sunix_pci_8s,
+ pbn_sunix_pci_16s,
++ pbn_titan_1_4000000,
++ pbn_titan_2_4000000,
++ pbn_titan_4_4000000,
++ pbn_titan_8_4000000,
+ pbn_moxa8250_2p,
+ pbn_moxa8250_4p,
+ pbn_moxa8250_8p,
+@@ -3770,6 +3774,34 @@ static struct pciserial_board pci_boards[] = {
+ .base_baud = 921600,
+ .uart_offset = 0x8,
+ },
++ [pbn_titan_1_4000000] = {
++ .flags = FL_BASE0,
++ .num_ports = 1,
++ .base_baud = 4000000,
++ .uart_offset = 0x200,
++ .first_offset = 0x1000,
++ },
++ [pbn_titan_2_4000000] = {
++ .flags = FL_BASE0,
++ .num_ports = 2,
++ .base_baud = 4000000,
++ .uart_offset = 0x200,
++ .first_offset = 0x1000,
++ },
++ [pbn_titan_4_4000000] = {
++ .flags = FL_BASE0,
++ .num_ports = 4,
++ .base_baud = 4000000,
++ .uart_offset = 0x200,
++ .first_offset = 0x1000,
++ },
++ [pbn_titan_8_4000000] = {
++ .flags = FL_BASE0,
++ .num_ports = 8,
++ .base_baud = 4000000,
++ .uart_offset = 0x200,
++ .first_offset = 0x1000,
++ },
+ [pbn_moxa8250_2p] = {
+ .flags = FL_BASE1,
+ .num_ports = 2,
+@@ -4721,22 +4753,22 @@ static const struct pci_device_id serial_pci_tbl[] = {
+ pbn_b0_4_921600 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_100E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_1_4000000 },
++ pbn_titan_1_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_2_4000000 },
++ pbn_titan_2_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_400E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_4_4000000 },
++ pbn_titan_4_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_800E,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_8_4000000 },
++ pbn_titan_8_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_2_4000000 },
++ pbn_titan_2_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200EISI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_oxsemi_2_4000000 },
++ pbn_titan_2_4000000 },
+ { PCI_VENDOR_ID_TITAN, PCI_DEVICE_ID_TITAN_200V3,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+ pbn_b0_bt_2_921600 },
+--
+2.35.1
+
--- /dev/null
+From 1d6f547a0f029d7ef44147c67dc839a967d9c3e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 18 Apr 2022 16:27:22 +0100
+Subject: serial: 8250: Fold EndRun device support into OxSemi Tornado code
+
+From: Maciej W. Rozycki <macro@orcam.me.uk>
+
+[ Upstream commit 1f32c65bad24b9787d3e52843de375430e3df822 ]
+
+The EndRun PTP/1588 dual serial port device is based on the Oxford
+Semiconductor OXPCIe952 UART device with the PCI vendor:device ID set
+for EndRun Technologies and uses the same sequence to determine the
+number of ports available. Despite that we have duplicate code
+specific to the EndRun device.
+
+Remove redundant code then and factor out OxSemi Tornado device
+detection.
+
+Signed-off-by: Maciej W. Rozycki <macro@orcam.me.uk>
+Reviewed-by: Andy Shevchenko <andy.shevchenko@gmail.com>
+Link: https://lore.kernel.org/r/alpine.DEB.2.21.2204181516220.9383@angie.orcam.me.uk
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/8250/8250_pci.c | 76 ++++++++++--------------------
+ 1 file changed, 25 insertions(+), 51 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index d2b38ae896d1..df10cc606582 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -994,41 +994,29 @@ static void pci_ite887x_exit(struct pci_dev *dev)
+ }
+
+ /*
+- * EndRun Technologies.
+- * Determine the number of ports available on the device.
++ * Oxford Semiconductor Inc.
++ * Check if an OxSemi device is part of the Tornado range of devices.
+ */
+ #define PCI_VENDOR_ID_ENDRUN 0x7401
+ #define PCI_DEVICE_ID_ENDRUN_1588 0xe100
+
+-static int pci_endrun_init(struct pci_dev *dev)
++static bool pci_oxsemi_tornado_p(struct pci_dev *dev)
+ {
+- u8 __iomem *p;
+- unsigned long deviceID;
+- unsigned int number_uarts = 0;
++ /* OxSemi Tornado devices are all 0xCxxx */
++ if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
++ (dev->device & 0xf000) != 0xc000)
++ return false;
+
+- /* EndRun device is all 0xexxx */
++ /* EndRun devices are all 0xExxx */
+ if (dev->vendor == PCI_VENDOR_ID_ENDRUN &&
+- (dev->device & 0xf000) != 0xe000)
+- return 0;
+-
+- p = pci_iomap(dev, 0, 5);
+- if (p == NULL)
+- return -ENOMEM;
++ (dev->device & 0xf000) != 0xe000)
++ return false;
+
+- deviceID = ioread32(p);
+- /* EndRun device */
+- if (deviceID == 0x07000200) {
+- number_uarts = ioread8(p + 4);
+- pci_dbg(dev, "%d ports detected on EndRun PCI Express device\n", number_uarts);
+- }
+- pci_iounmap(dev, p);
+- return number_uarts;
++ return true;
+ }
+
+ /*
+- * Oxford Semiconductor Inc.
+- * Check that device is part of the Tornado range of devices, then determine
+- * the number of ports available on the device.
++ * Determine the number of ports available on a Tornado device.
+ */
+ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+ {
+@@ -1036,9 +1024,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+ unsigned long deviceID;
+ unsigned int number_uarts = 0;
+
+- /* OxSemi Tornado devices are all 0xCxxx */
+- if (dev->vendor == PCI_VENDOR_ID_OXSEMI &&
+- (dev->device & 0xF000) != 0xC000)
++ if (!pci_oxsemi_tornado_p(dev))
+ return 0;
+
+ p = pci_iomap(dev, 0, 5);
+@@ -1049,7 +1035,10 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+ /* Tornado device */
+ if (deviceID == 0x07000200) {
+ number_uarts = ioread8(p + 4);
+- pci_dbg(dev, "%d ports detected on Oxford PCI Express device\n", number_uarts);
++ pci_dbg(dev, "%d ports detected on %s PCI Express device\n",
++ number_uarts,
++ dev->vendor == PCI_VENDOR_ID_ENDRUN ?
++ "EndRun" : "Oxford");
+ }
+ pci_iounmap(dev, p);
+ return number_uarts;
+@@ -2506,7 +2495,7 @@ static struct pci_serial_quirk pci_serial_quirks[] __refdata = {
+ .device = PCI_ANY_ID,
+ .subvendor = PCI_ANY_ID,
+ .subdevice = PCI_ANY_ID,
+- .init = pci_endrun_init,
++ .init = pci_oxsemi_tornado_init,
+ .setup = pci_default_setup,
+ },
+ /*
+@@ -2929,7 +2918,6 @@ enum pci_board_num_t {
+ pbn_panacom2,
+ pbn_panacom4,
+ pbn_plx_romulus,
+- pbn_endrun_2_3906250,
+ pbn_oxsemi,
+ pbn_oxsemi_1_3906250,
+ pbn_oxsemi_2_3906250,
+@@ -3455,20 +3443,6 @@ static struct pciserial_board pci_boards[] = {
+ .first_offset = 0x03,
+ },
+
+- /*
+- * EndRun Technologies
+- * Uses the size of PCI Base region 0 to
+- * signal now many ports are available
+- * 2 port 952 Uart support
+- */
+- [pbn_endrun_2_3906250] = {
+- .flags = FL_BASE0,
+- .num_ports = 2,
+- .base_baud = 3906250,
+- .uart_offset = 0x200,
+- .first_offset = 0x1000,
+- },
+-
+ /*
+ * This board uses the size of PCI Base region 0 to
+ * signal now many ports are available
+@@ -4400,13 +4374,6 @@ static const struct pci_device_id serial_pci_tbl[] = {
+ { PCI_VENDOR_ID_PLX, PCI_DEVICE_ID_PLX_ROMULUS,
+ 0x10b5, 0x106a, 0, 0,
+ pbn_plx_romulus },
+- /*
+- * EndRun Technologies. PCI express device range.
+- * EndRun PTP/1588 has 2 Native UARTs.
+- */
+- { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
+- PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+- pbn_endrun_2_3906250 },
+ /*
+ * Quatech cards. These actually have configurable clocks but for
+ * now we just use the default.
+@@ -4668,6 +4635,13 @@ static const struct pci_device_id serial_pci_tbl[] = {
+ { PCI_VENDOR_ID_DIGI, PCIE_DEVICE_ID_NEO_2_OX_IBM,
+ PCI_SUBVENDOR_ID_IBM, PCI_ANY_ID, 0, 0,
+ pbn_oxsemi_2_3906250 },
++ /*
++ * EndRun Technologies. PCI express device range.
++ * EndRun PTP/1588 has 2 Native UARTs utilizing OxSemi 952.
++ */
++ { PCI_VENDOR_ID_ENDRUN, PCI_DEVICE_ID_ENDRUN_1588,
++ PCI_ANY_ID, PCI_ANY_ID, 0, 0,
++ pbn_oxsemi_2_3906250 },
+
+ /*
+ * SBS Technologies, Inc. P-Octal and PMC-OCTPRO cards,
+--
+2.35.1
+
--- /dev/null
+From 06cd190b761ded2a88027b5ba72ea7ed03adb3e4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Oct 2021 16:51:45 +0300
+Subject: serial: 8250_pci: Refactor the loop in pci_ite887x_init()
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 35b4f17231923e2f64521bdf7a2793ce2c3c74a6 ]
+
+The loop can be refactored by using ARRAY_SIZE() instead of NULL terminator.
+This reduces code base and makes it easier to read and understand.
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Jiri Slaby <jslaby@kernel.org>
+Link: https://lore.kernel.org/r/20211022135147.70965-1-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/8250/8250_pci.c | 12 ++++--------
+ 1 file changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index bdc262b4109c..7ce755b47a3d 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -897,18 +897,16 @@ static int pci_netmos_init(struct pci_dev *dev)
+ /* enable IO_Space bit */
+ #define ITE_887x_POSIO_ENABLE (1 << 31)
+
++/* inta_addr are the configuration addresses of the ITE */
++static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0, 0x200, 0x280 };
+ static int pci_ite887x_init(struct pci_dev *dev)
+ {
+- /* inta_addr are the configuration addresses of the ITE */
+- static const short inta_addr[] = { 0x2a0, 0x2c0, 0x220, 0x240, 0x1e0,
+- 0x200, 0x280, 0 };
+ int ret, i, type;
+ struct resource *iobase = NULL;
+ u32 miscr, uartbar, ioport;
+
+ /* search for the base-ioport */
+- i = 0;
+- while (inta_addr[i] && iobase == NULL) {
++ for (i = 0; i < ARRAY_SIZE(inta_addr); i++) {
+ iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
+ "ite887x");
+ if (iobase != NULL) {
+@@ -925,12 +923,10 @@ static int pci_ite887x_init(struct pci_dev *dev)
+ break;
+ }
+ release_region(iobase->start, ITE_887x_IOSIZE);
+- iobase = NULL;
+ }
+- i++;
+ }
+
+- if (!inta_addr[i]) {
++ if (i == ARRAY_SIZE(inta_addr)) {
+ dev_err(&dev->dev, "ite887x: could not find iobase\n");
+ return -ENODEV;
+ }
+--
+2.35.1
+
--- /dev/null
+From 9b271be49f216a9d46dbc9a7d40301831faaebd1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 22 Oct 2021 16:51:47 +0300
+Subject: serial: 8250_pci: Replace dev_*() by pci_*() macros
+
+From: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+
+[ Upstream commit 1177384179416c7136e1348f07609e0da1ae6b91 ]
+
+PCI subsystem provides convenient shortcut macros for message printing.
+Use those macros instead of dev_*().
+
+Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
+Reviewed-by: Jiri Slaby <jslaby@kernel.org>
+Link: https://lore.kernel.org/r/20211022135147.70965-3-andriy.shevchenko@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/8250/8250_pci.c | 52 +++++++++++++-----------------
+ 1 file changed, 22 insertions(+), 30 deletions(-)
+
+diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
+index 7ce755b47a3d..d2b38ae896d1 100644
+--- a/drivers/tty/serial/8250/8250_pci.c
++++ b/drivers/tty/serial/8250/8250_pci.c
+@@ -75,13 +75,12 @@ static int pci_default_setup(struct serial_private*,
+
+ static void moan_device(const char *str, struct pci_dev *dev)
+ {
+- dev_err(&dev->dev,
+- "%s: %s\n"
++ pci_err(dev, "%s\n"
+ "Please send the output of lspci -vv, this\n"
+ "message (0x%04x,0x%04x,0x%04x,0x%04x), the\n"
+ "manufacturer and name of serial board or\n"
+ "modem board to <linux-serial@vger.kernel.org>.\n",
+- pci_name(dev), str, dev->vendor, dev->device,
++ str, dev->vendor, dev->device,
+ dev->subsystem_vendor, dev->subsystem_device);
+ }
+
+@@ -238,7 +237,7 @@ static int pci_inteli960ni_init(struct pci_dev *dev)
+ /* is firmware started? */
+ pci_read_config_dword(dev, 0x44, &oldval);
+ if (oldval == 0x00001000L) { /* RESET value */
+- dev_dbg(&dev->dev, "Local i960 firmware missing\n");
++ pci_dbg(dev, "Local i960 firmware missing\n");
+ return -ENODEV;
+ }
+ return 0;
+@@ -588,9 +587,8 @@ static int pci_timedia_probe(struct pci_dev *dev)
+ * (0,2,3,5,6: serial only -- 7,8,9: serial + parallel)
+ */
+ if ((dev->subsystem_device & 0x00f0) >= 0x70) {
+- dev_info(&dev->dev,
+- "ignoring Timedia subdevice %04x for parport_serial\n",
+- dev->subsystem_device);
++ pci_info(dev, "ignoring Timedia subdevice %04x for parport_serial\n",
++ dev->subsystem_device);
+ return -ENODEV;
+ }
+
+@@ -827,8 +825,7 @@ static int pci_netmos_9900_numports(struct pci_dev *dev)
+ if (sub_serports > 0)
+ return sub_serports;
+
+- dev_err(&dev->dev,
+- "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
++ pci_err(dev, "NetMos/Mostech serial driver ignoring port on ambiguous config.\n");
+ return 0;
+ }
+
+@@ -927,7 +924,7 @@ static int pci_ite887x_init(struct pci_dev *dev)
+ }
+
+ if (i == ARRAY_SIZE(inta_addr)) {
+- dev_err(&dev->dev, "ite887x: could not find iobase\n");
++ pci_err(dev, "could not find iobase\n");
+ return -ENODEV;
+ }
+
+@@ -1022,9 +1019,7 @@ static int pci_endrun_init(struct pci_dev *dev)
+ /* EndRun device */
+ if (deviceID == 0x07000200) {
+ number_uarts = ioread8(p + 4);
+- dev_dbg(&dev->dev,
+- "%d ports detected on EndRun PCI Express device\n",
+- number_uarts);
++ pci_dbg(dev, "%d ports detected on EndRun PCI Express device\n", number_uarts);
+ }
+ pci_iounmap(dev, p);
+ return number_uarts;
+@@ -1054,9 +1049,7 @@ static int pci_oxsemi_tornado_init(struct pci_dev *dev)
+ /* Tornado device */
+ if (deviceID == 0x07000200) {
+ number_uarts = ioread8(p + 4);
+- dev_dbg(&dev->dev,
+- "%d ports detected on Oxford PCI Express device\n",
+- number_uarts);
++ pci_dbg(dev, "%d ports detected on Oxford PCI Express device\n", number_uarts);
+ }
+ pci_iounmap(dev, p);
+ return number_uarts;
+@@ -1116,15 +1109,15 @@ static struct quatech_feature quatech_cards[] = {
+ { 0, }
+ };
+
+-static int pci_quatech_amcc(u16 devid)
++static int pci_quatech_amcc(struct pci_dev *dev)
+ {
+ struct quatech_feature *qf = &quatech_cards[0];
+ while (qf->devid) {
+- if (qf->devid == devid)
++ if (qf->devid == dev->device)
+ return qf->amcc;
+ qf++;
+ }
+- pr_err("quatech: unknown port type '0x%04X'.\n", devid);
++ pci_err(dev, "unknown port type '0x%04X'.\n", dev->device);
+ return 0;
+ };
+
+@@ -1287,7 +1280,7 @@ static int pci_quatech_rs422(struct uart_8250_port *port)
+
+ static int pci_quatech_init(struct pci_dev *dev)
+ {
+- if (pci_quatech_amcc(dev->device)) {
++ if (pci_quatech_amcc(dev)) {
+ unsigned long base = pci_resource_start(dev, 0);
+ if (base) {
+ u32 tmp;
+@@ -1311,7 +1304,7 @@ static int pci_quatech_setup(struct serial_private *priv,
+ port->port.uartclk = pci_quatech_clock(port);
+ /* For now just warn about RS422 */
+ if (pci_quatech_rs422(port))
+- pr_warn("quatech: software control of RS422 features not currently supported.\n");
++ pci_warn(priv->dev, "software control of RS422 features not currently supported.\n");
+ return pci_default_setup(priv, board, port, idx);
+ }
+
+@@ -1525,7 +1518,7 @@ static int pci_fintek_setup(struct serial_private *priv,
+ /* Get the io address from configuration space */
+ pci_read_config_word(pdev, config_base + 4, &iobase);
+
+- dev_dbg(&pdev->dev, "%s: idx=%d iobase=0x%x", __func__, idx, iobase);
++ pci_dbg(pdev, "idx=%d iobase=0x%x", idx, iobase);
+
+ port->port.iotype = UPIO_PORT;
+ port->port.iobase = iobase;
+@@ -1689,7 +1682,7 @@ static int skip_tx_en_setup(struct serial_private *priv,
+ struct uart_8250_port *port, int idx)
+ {
+ port->port.quirks |= UPQ_NO_TXEN_TEST;
+- dev_dbg(&priv->dev->dev,
++ pci_dbg(priv->dev,
+ "serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n",
+ priv->dev->vendor, priv->dev->device,
+ priv->dev->subsystem_vendor, priv->dev->subsystem_device);
+@@ -4007,12 +4000,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
+ uart.port.irq = 0;
+ } else {
+ if (pci_match_id(pci_use_msi, dev)) {
+- dev_dbg(&dev->dev, "Using MSI(-X) interrupts\n");
++ pci_dbg(dev, "Using MSI(-X) interrupts\n");
+ pci_set_master(dev);
+ uart.port.flags &= ~UPF_SHARE_IRQ;
+ rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_ALL_TYPES);
+ } else {
+- dev_dbg(&dev->dev, "Using legacy interrupts\n");
++ pci_dbg(dev, "Using legacy interrupts\n");
+ rc = pci_alloc_irq_vectors(dev, 1, 1, PCI_IRQ_LEGACY);
+ }
+ if (rc < 0) {
+@@ -4030,12 +4023,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)
+ if (quirk->setup(priv, board, &uart, i))
+ break;
+
+- dev_dbg(&dev->dev, "Setup PCI port: port %lx, irq %d, type %d\n",
++ pci_dbg(dev, "Setup PCI port: port %lx, irq %d, type %d\n",
+ uart.port.iobase, uart.port.irq, uart.port.iotype);
+
+ priv->line[i] = serial8250_register_8250_port(&uart);
+ if (priv->line[i] < 0) {
+- dev_err(&dev->dev,
++ pci_err(dev,
+ "Couldn't register serial port %lx, irq %d, type %d, error %d\n",
+ uart.port.iobase, uart.port.irq,
+ uart.port.iotype, priv->line[i]);
+@@ -4131,8 +4124,7 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
+ }
+
+ if (ent->driver_data >= ARRAY_SIZE(pci_boards)) {
+- dev_err(&dev->dev, "invalid driver_data: %ld\n",
+- ent->driver_data);
++ pci_err(dev, "invalid driver_data: %ld\n", ent->driver_data);
+ return -EINVAL;
+ }
+
+@@ -4215,7 +4207,7 @@ static int pciserial_resume_one(struct device *dev)
+ err = pci_enable_device(pdev);
+ /* FIXME: We cannot simply error out here */
+ if (err)
+- dev_err(dev, "Unable to re-enable ports, trying to continue.\n");
++ pci_err(pdev, "Unable to re-enable ports, trying to continue.\n");
+ pciserial_resume_ports(priv);
+ }
+ return 0;
+--
+2.35.1
+
input-gscps2-check-return-value-of-ioremap-in-gscps2_probe.patch
__follow_mount_rcu-verify-that-mount_lock-remains-unchanged.patch
spmi-trace-fix-stack-out-of-bound-access-in-spmi-tracing-functions.patch
+drm-i915-dg1-update-dmc_debug3-register.patch
+drm-mediatek-allow-commands-to-be-sent-during-video-.patch
+drm-mediatek-keep-dsi-as-lp00-before-dcs-cmds-transf.patch
+hid-ignore-battery-for-elan-touchscreen-on-hp-spectr.patch
+hid-hid-input-add-surface-go-battery-quirk.patch
+scsi-qla2xxx-turn-off-multi-queue-for-8g-adapters.patch-18489
+scsi-qla2xxx-fix-losing-fcp-2-targets-during-port-pe.patch
+scsi-qla2xxx-fix-losing-fcp-2-targets-on-long-port-d.patch
+scsi-qla2xxx-fix-erroneous-mailbox-timeout-after-pci.patch
+drm-vc4-drv-adopt-the-dma-configuration-from-the-hvs.patch
+mtd-rawnand-add-a-helper-to-clarify-the-interface-co.patch
+mtd-rawnand-arasan-check-the-proposed-data-interface.patch
+mtd-rawnand-add-nv-ddr-timings.patch
+mtd-rawnand-arasan-fix-a-macro-parameter.patch
+mtd-rawnand-arasan-support-nv-ddr-interface.patch
+mtd-rawnand-arasan-fix-clock-rate-in-nv-ddr.patch
+usbnet-smsc95xx-don-t-clear-read-only-phy-interrupt.patch
+usbnet-smsc95xx-avoid-link-settings-race-on-interrup.patch
+firmware-arm_scpi-ensure-scpi_info-is-not-assigned-i.patch
+__follow_mount_rcu-verify-that-mount_lock-remains-un.patch
+intel_th-pci-add-meteor-lake-p-support.patch
+intel_th-pci-add-raptor-lake-s-pch-support.patch
+intel_th-pci-add-raptor-lake-s-cpu-support.patch
+kvm-set_msr_mce-permit-guests-to-ignore-single-bit-e.patch
+kvm-x86-signal-gp-not-eperm-on-bad-wrmsr-mci_ctl-sta.patch
+iommu-vt-d-avoid-invalid-memory-access-via-node_onli.patch
+pci-aer-write-aer-capability-only-when-we-control-it.patch
+pci-err-bind-rcec-devices-to-the-root-port-driver.patch
+pci-err-rename-reset_link-to-reset_subordinates.patch
+pci-err-simplify-by-using-pci_upstream_bridge.patch
+pci-err-simplify-by-computing-pci_pcie_type-once.patch
+pci-err-use-bridge-for-clarity-in-pcie_do_recovery.patch
+pci-err-avoid-negated-conditional-for-clarity.patch
+pci-err-add-pci_walk_bridge-to-pcie_do_recovery.patch
+pci-err-recover-from-rcec-aer-errors.patch
+pci-aer-iterate-over-error-counters-instead-of-error.patch
+serial-8250-dissociate-4mhz-titan-ports-from-oxford-.patch
+serial-8250-correct-the-clock-for-oxsemi-pcie-device.patch
+serial-8250_pci-refactor-the-loop-in-pci_ite887x_ini.patch
+serial-8250_pci-replace-dev_-by-pci_-macros.patch
+serial-8250-fold-endrun-device-support-into-oxsemi-t.patch
+dm-writecache-set-a-default-max_writeback_jobs.patch
+x86-olpc-fix-logical-not-is-only-applied-to-the-left.patch
+kexec-keys-s390-make-use-of-built-in-and-secondary-k.patch
+dm-thin-fix-use-after-free-crash-in-dm_sm_register_t.patch
+timekeeping-contribute-wall-clock-to-rng-on-time-cha.patch
+um-allow-pm-with-suspend-to-idle.patch
+um-seed-rng-using-host-os-rng.patch
+scsi-qla2xxx-fix-discovery-issues-in-fc-al-topology.patch-16688
+scsi-qla2xxx-update-manufacturer-details.patch
+spmi-trace-fix-stack-out-of-bound-access-in-spmi-tra.patch
+btrfs-reject-log-replay-if-there-is-unsupported-ro-c.patch
+btrfs-reset-block-group-chunk-force-if-we-have-to-wa.patch
+acpi-cppc-do-not-prevent-cppc-from-working-in-the-fu.patch
+kvm-ppc-book3s-hv-remove-virt-mode-checks-from-real-.patch
+powerpc-powernv-kvm-use-darn-for-h_random-on-power9.patch
+kvm-vmx-drop-guest-cpuid-check-for-vmxe-in-vmx_set_c.patch
+kvm-vmx-drop-explicit-nested-check-from-vmx_set_cr4.patch
+kvm-svm-drop-vmxe-check-from-svm_set_cr4.patch
+kvm-x86-move-vendor-cr4-validity-check-to-dedicated-.patch
+kvm-nvmx-inject-ud-if-vmxon-is-attempted-with-incomp.patch
+kvm-x86-pmu-preserve-ia32_perf_capabilities-across-c.patch
+kvm-x86-pmu-use-binary-search-to-check-filtered-even.patch
+kvm-x86-pmu-use-different-raw-event-masks-for-amd-an.patch
+kvm-x86-pmu-introduce-the-ctrl_mask-value-for-fixed-.patch
+kvm-vmx-mark-all-perf_global_-ovf-_ctrl-bits-reserve.patch
+kvm-x86-pmu-ignore-pmu-global_ctrl-check-if-vpmu-doe.patch
--- /dev/null
+From 351d94f31fbae04e89a91d46f3bc382b6b105a14 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 27 Jun 2022 16:55:12 -0700
+Subject: spmi: trace: fix stack-out-of-bound access in SPMI tracing functions
+
+From: David Collins <quic_collinsd@quicinc.com>
+
+[ Upstream commit 2af28b241eea816e6f7668d1954f15894b45d7e3 ]
+
+trace_spmi_write_begin() and trace_spmi_read_end() both call
+memcpy() with a length of "len + 1". This leads to one extra
+byte being read beyond the end of the specified buffer. Fix
+this out-of-bound memory access by using a length of "len"
+instead.
+
+Here is a KASAN log showing the issue:
+
+BUG: KASAN: stack-out-of-bounds in trace_event_raw_event_spmi_read_end+0x1d0/0x234
+Read of size 2 at addr ffffffc0265b7540 by task thermal@2.0-ser/1314
+...
+Call trace:
+ dump_backtrace+0x0/0x3e8
+ show_stack+0x2c/0x3c
+ dump_stack_lvl+0xdc/0x11c
+ print_address_description+0x74/0x384
+ kasan_report+0x188/0x268
+ kasan_check_range+0x270/0x2b0
+ memcpy+0x90/0xe8
+ trace_event_raw_event_spmi_read_end+0x1d0/0x234
+ spmi_read_cmd+0x294/0x3ac
+ spmi_ext_register_readl+0x84/0x9c
+ regmap_spmi_ext_read+0x144/0x1b0 [regmap_spmi]
+ _regmap_raw_read+0x40c/0x754
+ regmap_raw_read+0x3a0/0x514
+ regmap_bulk_read+0x418/0x494
+ adc5_gen3_poll_wait_hs+0xe8/0x1e0 [qcom_spmi_adc5_gen3]
+ ...
+ __arm64_sys_read+0x4c/0x60
+ invoke_syscall+0x80/0x218
+ el0_svc_common+0xec/0x1c8
+ ...
+
+addr ffffffc0265b7540 is located in stack of task thermal@2.0-ser/1314 at offset 32 in frame:
+ adc5_gen3_poll_wait_hs+0x0/0x1e0 [qcom_spmi_adc5_gen3]
+
+this frame has 1 object:
+ [32, 33) 'status'
+
+Memory state around the buggy address:
+ ffffffc0265b7400: 00 00 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1
+ ffffffc0265b7480: 04 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 00 00
+>ffffffc0265b7500: 00 00 00 00 f1 f1 f1 f1 01 f3 f3 f3 00 00 00 00
+ ^
+ ffffffc0265b7580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+ ffffffc0265b7600: f1 f1 f1 f1 01 f2 07 f2 f2 f2 01 f3 00 00 00 00
+==================================================================
+
+Fixes: a9fce374815d ("spmi: add command tracepoints for SPMI")
+Cc: stable@vger.kernel.org
+Reviewed-by: Stephen Boyd <sboyd@kernel.org>
+Acked-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: David Collins <quic_collinsd@quicinc.com>
+Link: https://lore.kernel.org/r/20220627235512.2272783-1-quic_collinsd@quicinc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/trace/events/spmi.h | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+diff --git a/include/trace/events/spmi.h b/include/trace/events/spmi.h
+index 8b60efe18ba6..a6819fd85cdf 100644
+--- a/include/trace/events/spmi.h
++++ b/include/trace/events/spmi.h
+@@ -21,15 +21,15 @@ TRACE_EVENT(spmi_write_begin,
+ __field ( u8, sid )
+ __field ( u16, addr )
+ __field ( u8, len )
+- __dynamic_array ( u8, buf, len + 1 )
++ __dynamic_array ( u8, buf, len )
+ ),
+
+ TP_fast_assign(
+ __entry->opcode = opcode;
+ __entry->sid = sid;
+ __entry->addr = addr;
+- __entry->len = len + 1;
+- memcpy(__get_dynamic_array(buf), buf, len + 1);
++ __entry->len = len;
++ memcpy(__get_dynamic_array(buf), buf, len);
+ ),
+
+ TP_printk("opc=%d sid=%02d addr=0x%04x len=%d buf=0x[%*phD]",
+@@ -92,7 +92,7 @@ TRACE_EVENT(spmi_read_end,
+ __field ( u16, addr )
+ __field ( int, ret )
+ __field ( u8, len )
+- __dynamic_array ( u8, buf, len + 1 )
++ __dynamic_array ( u8, buf, len )
+ ),
+
+ TP_fast_assign(
+@@ -100,8 +100,8 @@ TRACE_EVENT(spmi_read_end,
+ __entry->sid = sid;
+ __entry->addr = addr;
+ __entry->ret = ret;
+- __entry->len = len + 1;
+- memcpy(__get_dynamic_array(buf), buf, len + 1);
++ __entry->len = len;
++ memcpy(__get_dynamic_array(buf), buf, len);
+ ),
+
+ TP_printk("opc=%d sid=%02d addr=0x%04x ret=%d len=%02d buf=0x[%*phD]",
+--
+2.35.1
+
--- /dev/null
+From 43c7f2a5d3c6870d0386ab82890153f85085f86e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 17 Jul 2022 23:53:34 +0200
+Subject: timekeeping: contribute wall clock to rng on time change
+
+From: Jason A. Donenfeld <Jason@zx2c4.com>
+
+[ Upstream commit b8ac29b40183a6038919768b5d189c9bd91ce9b4 ]
+
+The rng's random_init() function contributes the real time to the rng at
+boot time, so that events can at least start in relation to something
+particular in the real world. But this clock might not yet be set that
+point in boot, so nothing is contributed. In addition, the relation
+between minor clock changes from, say, NTP, and the cycle counter is
+potentially useful entropic data.
+
+This commit addresses this by mixing in a time stamp on calls to
+settimeofday and adjtimex. No entropy is credited in doing so, so it
+doesn't make initialization faster, but it is still useful input to
+have.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
+Reviewed-by: Eric Biggers <ebiggers@google.com>
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/time/timekeeping.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
+index e12ce2821dba..d9b48f7a35e0 100644
+--- a/kernel/time/timekeeping.c
++++ b/kernel/time/timekeeping.c
+@@ -23,6 +23,7 @@
+ #include <linux/pvclock_gtod.h>
+ #include <linux/compiler.h>
+ #include <linux/audit.h>
++#include <linux/random.h>
+
+ #include "tick-internal.h"
+ #include "ntp_internal.h"
+@@ -1330,8 +1331,10 @@ int do_settimeofday64(const struct timespec64 *ts)
+ /* signal hrtimers about time change */
+ clock_was_set();
+
+- if (!ret)
++ if (!ret) {
+ audit_tk_injoffset(ts_delta);
++ add_device_randomness(ts, sizeof(*ts));
++ }
+
+ return ret;
+ }
+@@ -2410,6 +2413,7 @@ int do_adjtimex(struct __kernel_timex *txc)
+ ret = timekeeping_validate_timex(txc);
+ if (ret)
+ return ret;
++ add_device_randomness(txc, sizeof(*txc));
+
+ if (txc->modes & ADJ_SETOFFSET) {
+ struct timespec64 delta;
+@@ -2427,6 +2431,7 @@ int do_adjtimex(struct __kernel_timex *txc)
+ audit_ntp_init(&ad);
+
+ ktime_get_real_ts64(&ts);
++ add_device_randomness(&ts, sizeof(ts));
+
+ raw_spin_lock_irqsave(&timekeeper_lock, flags);
+ write_seqcount_begin(&tk_core.seq);
+--
+2.35.1
+
--- /dev/null
+From 97b9441f7d5edb5b553f0ae8d13dcb79d597bc5e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 2 Dec 2020 20:58:06 +0100
+Subject: um: Allow PM with suspend-to-idle
+
+From: Johannes Berg <johannes.berg@intel.com>
+
+[ Upstream commit 92dcd3d31843fbe1a95d880dc912e1f6beac6632 ]
+
+In order to be able to experiment with suspend in UML, add the
+minimal work to be able to suspend (s2idle) an instance of UML,
+and be able to wake it back up from that state with the USR1
+signal sent to the main UML process.
+
+Signed-off-by: Johannes Berg <johannes.berg@intel.com>
+Acked-By: Anton Ivanov <anton.ivanov@cambridgegreys.com>
+Signed-off-by: Richard Weinberger <richard@nod.at>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/Kconfig | 5 +++++
+ arch/um/include/shared/kern_util.h | 2 ++
+ arch/um/include/shared/os.h | 1 +
+ arch/um/kernel/um_arch.c | 25 +++++++++++++++++++++++++
+ arch/um/os-Linux/signal.c | 14 +++++++++++++-
+ 5 files changed, 46 insertions(+), 1 deletion(-)
+
+diff --git a/arch/um/Kconfig b/arch/um/Kconfig
+index 4b799fad8b48..1c57599b82fa 100644
+--- a/arch/um/Kconfig
++++ b/arch/um/Kconfig
+@@ -192,3 +192,8 @@ config UML_TIME_TRAVEL_SUPPORT
+ endmenu
+
+ source "arch/um/drivers/Kconfig"
++
++config ARCH_SUSPEND_POSSIBLE
++ def_bool y
++
++source "kernel/power/Kconfig"
+diff --git a/arch/um/include/shared/kern_util.h b/arch/um/include/shared/kern_util.h
+index ccafb62e8cce..9c08e728a675 100644
+--- a/arch/um/include/shared/kern_util.h
++++ b/arch/um/include/shared/kern_util.h
+@@ -39,6 +39,8 @@ extern int is_syscall(unsigned long addr);
+
+ extern void timer_handler(int sig, struct siginfo *unused_si, struct uml_pt_regs *regs);
+
++extern void uml_pm_wake(void);
++
+ extern int start_uml(void);
+ extern void paging_init(void);
+
+diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
+index f467d28fc0b4..2f31d44d892e 100644
+--- a/arch/um/include/shared/os.h
++++ b/arch/um/include/shared/os.h
+@@ -241,6 +241,7 @@ extern int set_signals(int enable);
+ extern int set_signals_trace(int enable);
+ extern int os_is_signal_stack(void);
+ extern void deliver_alarm(void);
++extern void register_pm_wake_signal(void);
+
+ /* util.c */
+ extern void stack_protections(unsigned long address);
+diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
+index 26af24b5d900..52e2e2a3e4ae 100644
+--- a/arch/um/kernel/um_arch.c
++++ b/arch/um/kernel/um_arch.c
+@@ -13,6 +13,7 @@
+ #include <linux/sched.h>
+ #include <linux/sched/task.h>
+ #include <linux/kmsg_dump.h>
++#include <linux/suspend.h>
+
+ #include <asm/processor.h>
+ #include <asm/sections.h>
+@@ -385,3 +386,27 @@ void *text_poke(void *addr, const void *opcode, size_t len)
+ void text_poke_sync(void)
+ {
+ }
++
++#ifdef CONFIG_PM_SLEEP
++void uml_pm_wake(void)
++{
++ pm_system_wakeup();
++}
++
++static int init_pm_wake_signal(void)
++{
++ /*
++ * In external time-travel mode we can't use signals to wake up
++ * since that would mess with the scheduling. We'll have to do
++ * some additional work to support wakeup on virtio devices or
++ * similar, perhaps implementing a fake RTC controller that can
++ * trigger wakeup (and request the appropriate scheduling from
++ * the external scheduler when going to suspend.)
++ */
++ if (time_travel_mode != TT_MODE_EXTERNAL)
++ register_pm_wake_signal();
++ return 0;
++}
++
++late_initcall(init_pm_wake_signal);
++#endif
+diff --git a/arch/um/os-Linux/signal.c b/arch/um/os-Linux/signal.c
+index b58bc68cbe64..0a2ea84033b4 100644
+--- a/arch/um/os-Linux/signal.c
++++ b/arch/um/os-Linux/signal.c
+@@ -136,6 +136,16 @@ void set_sigstack(void *sig_stack, int size)
+ panic("enabling signal stack failed, errno = %d\n", errno);
+ }
+
++static void sigusr1_handler(int sig, struct siginfo *unused_si, mcontext_t *mc)
++{
++ uml_pm_wake();
++}
++
++void register_pm_wake_signal(void)
++{
++ set_handler(SIGUSR1);
++}
++
+ static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = {
+ [SIGSEGV] = sig_handler,
+ [SIGBUS] = sig_handler,
+@@ -145,7 +155,9 @@ static void (*handlers[_NSIG])(int sig, struct siginfo *si, mcontext_t *mc) = {
+
+ [SIGIO] = sig_handler,
+ [SIGWINCH] = sig_handler,
+- [SIGALRM] = timer_alarm_handler
++ [SIGALRM] = timer_alarm_handler,
++
++ [SIGUSR1] = sigusr1_handler,
+ };
+
+ static void hard_handler(int sig, siginfo_t *si, void *p)
+--
+2.35.1
+
--- /dev/null
+From c79b44779df18e44ff12f900c44285c5ae47d363 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 Jul 2022 01:12:21 +0200
+Subject: um: seed rng using host OS rng
+
+From: Jason A. Donenfeld <Jason@zx2c4.com>
+
+[ Upstream commit 0b9ba6135d7f18b82f3d8bebb55ded725ba88e0e ]
+
+UML generally does not provide access to special CPU instructions like
+RDRAND, and execution tends to be rather deterministic, with no real
+hardware interrupts, making good randomness really very hard, if not
+all together impossible. Not only is this a security eyebrow raiser, but
+it's also quite annoying when trying to do various pieces of UML-based
+automation that takes a long time to boot, if ever.
+
+Fix this by trivially calling getrandom() in the host and using that
+seed as "bootloader randomness", which initializes the rng immediately
+at UML boot.
+
+The old behavior can be restored the same way as on any other arch, by
+way of CONFIG_TRUST_BOOTLOADER_RANDOMNESS=n or
+random.trust_bootloader=0. So seen from that perspective, this just
+makes UML act like other archs, which is positive in its own right.
+
+Additionally, wire up arch_get_random_{int,long}() in the same way, so
+that reseeds can also make use of the host RNG, controllable by
+CONFIG_TRUST_CPU_RANDOMNESS and random.trust_cpu, per usual.
+
+Cc: stable@vger.kernel.org
+Acked-by: Johannes Berg <johannes@sipsolutions.net>
+Acked-By: Anton Ivanov <anton.ivanov@cambridgegreys.com>
+Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/um/include/asm/archrandom.h | 30 ++++++++++++++++++++++++++++++
+ arch/um/include/shared/os.h | 7 +++++++
+ arch/um/kernel/um_arch.c | 8 ++++++++
+ arch/um/os-Linux/util.c | 6 ++++++
+ 4 files changed, 51 insertions(+)
+ create mode 100644 arch/um/include/asm/archrandom.h
+
+diff --git a/arch/um/include/asm/archrandom.h b/arch/um/include/asm/archrandom.h
+new file mode 100644
+index 000000000000..2f24cb96391d
+--- /dev/null
++++ b/arch/um/include/asm/archrandom.h
+@@ -0,0 +1,30 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++#ifndef __ASM_UM_ARCHRANDOM_H__
++#define __ASM_UM_ARCHRANDOM_H__
++
++#include <linux/types.h>
++
++/* This is from <os.h>, but better not to #include that in a global header here. */
++ssize_t os_getrandom(void *buf, size_t len, unsigned int flags);
++
++static inline bool __must_check arch_get_random_long(unsigned long *v)
++{
++ return os_getrandom(v, sizeof(*v), 0) == sizeof(*v);
++}
++
++static inline bool __must_check arch_get_random_int(unsigned int *v)
++{
++ return os_getrandom(v, sizeof(*v), 0) == sizeof(*v);
++}
++
++static inline bool __must_check arch_get_random_seed_long(unsigned long *v)
++{
++ return false;
++}
++
++static inline bool __must_check arch_get_random_seed_int(unsigned int *v)
++{
++ return false;
++}
++
++#endif
+diff --git a/arch/um/include/shared/os.h b/arch/um/include/shared/os.h
+index 2f31d44d892e..a339938b85a0 100644
+--- a/arch/um/include/shared/os.h
++++ b/arch/um/include/shared/os.h
+@@ -12,6 +12,12 @@
+ #include <irq_user.h>
+ #include <longjmp.h>
+ #include <mm_id.h>
++/* This is to get size_t */
++#ifndef __UM_HOST__
++#include <linux/types.h>
++#else
++#include <sys/types.h>
++#endif
+
+ #define CATCH_EINTR(expr) while ((errno = 0, ((expr) < 0)) && (errno == EINTR))
+
+@@ -248,6 +254,7 @@ extern void stack_protections(unsigned long address);
+ extern int raw(int fd);
+ extern void setup_machinename(char *machine_out);
+ extern void setup_hostinfo(char *buf, int len);
++extern ssize_t os_getrandom(void *buf, size_t len, unsigned int flags);
+ extern void os_dump_core(void) __attribute__ ((noreturn));
+ extern void um_early_printk(const char *s, unsigned int n);
+ extern void os_fix_helper_signals(void);
+diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c
+index 52e2e2a3e4ae..ecef61f9aadf 100644
+--- a/arch/um/kernel/um_arch.c
++++ b/arch/um/kernel/um_arch.c
+@@ -14,6 +14,7 @@
+ #include <linux/sched/task.h>
+ #include <linux/kmsg_dump.h>
+ #include <linux/suspend.h>
++#include <linux/random.h>
+
+ #include <asm/processor.h>
+ #include <asm/sections.h>
+@@ -342,6 +343,8 @@ int __init __weak read_initrd(void)
+
+ void __init setup_arch(char **cmdline_p)
+ {
++ u8 rng_seed[32];
++
+ stack_protections((unsigned long) &init_thread_info);
+ setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem);
+ mem_total_pages(physmem_size, iomem_size, highmem);
+@@ -351,6 +354,11 @@ void __init setup_arch(char **cmdline_p)
+ strlcpy(boot_command_line, command_line, COMMAND_LINE_SIZE);
+ *cmdline_p = command_line;
+ setup_hostinfo(host_info, sizeof host_info);
++
++ if (os_getrandom(rng_seed, sizeof(rng_seed), 0) == sizeof(rng_seed)) {
++ add_bootloader_randomness(rng_seed, sizeof(rng_seed));
++ memzero_explicit(rng_seed, sizeof(rng_seed));
++ }
+ }
+
+ void __init check_bugs(void)
+diff --git a/arch/um/os-Linux/util.c b/arch/um/os-Linux/util.c
+index 07327425d06e..fab664203f30 100644
+--- a/arch/um/os-Linux/util.c
++++ b/arch/um/os-Linux/util.c
+@@ -13,6 +13,7 @@
+ #include <sys/wait.h>
+ #include <sys/mman.h>
+ #include <sys/utsname.h>
++#include <sys/random.h>
+ #include <init.h>
+ #include <os.h>
+
+@@ -95,6 +96,11 @@ static inline void __attribute__ ((noreturn)) uml_abort(void)
+ exit(127);
+ }
+
++ssize_t os_getrandom(void *buf, size_t len, unsigned int flags)
++{
++ return getrandom(buf, len, flags);
++}
++
+ /*
+ * UML helper threads must not handle SIGWINCH/INT/TERM
+ */
+--
+2.35.1
+
--- /dev/null
+From 77f46e42b590ac5315af78c209a2a5bc6b649b9c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 May 2022 10:42:04 +0200
+Subject: usbnet: smsc95xx: Avoid link settings race on interrupt reception
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit 8960f878e39fadc03d74292a6731f1e914cf2019 ]
+
+When a PHY interrupt is signaled, the SMSC LAN95xx driver updates the
+MAC full duplex mode and PHY flow control registers based on cached data
+in struct phy_device:
+
+ smsc95xx_status() # raises EVENT_LINK_RESET
+ usbnet_deferred_kevent()
+ smsc95xx_link_reset() # uses cached data in phydev
+
+Simultaneously, phylib polls link status once per second and updates
+that cached data:
+
+ phy_state_machine()
+ phy_check_link_status()
+ phy_read_status()
+ lan87xx_read_status()
+ genphy_read_status() # updates cached data in phydev
+
+If smsc95xx_link_reset() wins the race against genphy_read_status(),
+the registers may be updated based on stale data.
+
+E.g. if the link was previously down, phydev->duplex is set to
+DUPLEX_UNKNOWN and that's what smsc95xx_link_reset() will use, even
+though genphy_read_status() may update it to DUPLEX_FULL afterwards.
+
+PHY interrupts are currently only enabled on suspend to trigger wakeup,
+so the impact of the race is limited, but we're about to enable them
+perpetually.
+
+Avoid the race by delaying execution of smsc95xx_link_reset() until
+phy_state_machine() has done its job and calls back via
+smsc95xx_handle_link_change().
+
+Signaling EVENT_LINK_RESET on wakeup is not necessary because phylib
+picks up link status changes through polling. So drop the declaration
+of a ->link_reset() callback.
+
+Note that the semicolon on a line by itself added in smsc95xx_status()
+is a placeholder for a function call which will be added in a subsequent
+commit. That function call will actually handle the INT_ENP_PHY_INT_
+interrupt.
+
+Tested-by: Oleksij Rempel <o.rempel@pengutronix.de> # LAN9514/9512/9500
+Tested-by: Ferry Toth <fntoth@gmail.com> # LAN9514
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/smsc95xx.c | 16 +++++++++-------
+ 1 file changed, 9 insertions(+), 7 deletions(-)
+
+diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
+index b1d7331c3c5c..65d42f5d42a3 100644
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -564,7 +564,7 @@ static int smsc95xx_phy_update_flowcontrol(struct usbnet *dev)
+ return smsc95xx_write_reg(dev, AFC_CFG, afc_cfg);
+ }
+
+-static int smsc95xx_link_reset(struct usbnet *dev)
++static void smsc95xx_mac_update_fullduplex(struct usbnet *dev)
+ {
+ struct smsc95xx_priv *pdata = dev->driver_priv;
+ unsigned long flags;
+@@ -581,14 +581,16 @@ static int smsc95xx_link_reset(struct usbnet *dev)
+ spin_unlock_irqrestore(&pdata->mac_cr_lock, flags);
+
+ ret = smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr);
+- if (ret < 0)
+- return ret;
++ if (ret < 0) {
++ if (ret != -ENODEV)
++ netdev_warn(dev->net,
++ "Error updating MAC full duplex mode\n");
++ return;
++ }
+
+ ret = smsc95xx_phy_update_flowcontrol(dev);
+ if (ret < 0)
+ netdev_warn(dev->net, "Error updating PHY flow control\n");
+-
+- return ret;
+ }
+
+ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
+@@ -605,7 +607,7 @@ static void smsc95xx_status(struct usbnet *dev, struct urb *urb)
+ netif_dbg(dev, link, dev->net, "intdata: 0x%08X\n", intdata);
+
+ if (intdata & INT_ENP_PHY_INT_)
+- usbnet_defer_kevent(dev, EVENT_LINK_RESET);
++ ;
+ else
+ netdev_warn(dev->net, "unexpected interrupt, intdata=0x%08X\n",
+ intdata);
+@@ -1062,6 +1064,7 @@ static void smsc95xx_handle_link_change(struct net_device *net)
+ struct usbnet *dev = netdev_priv(net);
+
+ phy_print_status(net->phydev);
++ smsc95xx_mac_update_fullduplex(dev);
+ usbnet_defer_kevent(dev, EVENT_LINK_CHANGE);
+ }
+
+@@ -1968,7 +1971,6 @@ static const struct driver_info smsc95xx_info = {
+ .description = "smsc95xx USB 2.0 Ethernet",
+ .bind = smsc95xx_bind,
+ .unbind = smsc95xx_unbind,
+- .link_reset = smsc95xx_link_reset,
+ .reset = smsc95xx_reset,
+ .check_connect = smsc95xx_start_phy,
+ .stop = smsc95xx_stop,
+--
+2.35.1
+
--- /dev/null
+From 18dca9bfef91831a1cadcb018b0e1ce0e88ae608 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 12 May 2022 10:42:02 +0200
+Subject: usbnet: smsc95xx: Don't clear read-only PHY interrupt
+
+From: Lukas Wunner <lukas@wunner.de>
+
+[ Upstream commit 3108871f19221372b251f7da1ac38736928b5b3a ]
+
+Upon receiving data from the Interrupt Endpoint, the SMSC LAN95xx driver
+attempts to clear the signaled interrupts by writing "all ones" to the
+Interrupt Status Register.
+
+However the driver only ever enables a single type of interrupt, namely
+the PHY Interrupt. And according to page 119 of the LAN950x datasheet,
+its bit in the Interrupt Status Register is read-only. There's no other
+way to clear it than in a separate PHY register:
+
+https://www.microchip.com/content/dam/mchp/documents/UNG/ProductDocuments/DataSheets/LAN950x-Data-Sheet-DS00001875D.pdf
+
+Consequently, writing "all ones" to the Interrupt Status Register is
+pointless and can be dropped.
+
+Tested-by: Oleksij Rempel <o.rempel@pengutronix.de> # LAN9514/9512/9500
+Tested-by: Ferry Toth <fntoth@gmail.com> # LAN9514
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/usb/smsc95xx.c | 4 ----
+ 1 file changed, 4 deletions(-)
+
+diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c
+index e5b744851146..b1d7331c3c5c 100644
+--- a/drivers/net/usb/smsc95xx.c
++++ b/drivers/net/usb/smsc95xx.c
+@@ -570,10 +570,6 @@ static int smsc95xx_link_reset(struct usbnet *dev)
+ unsigned long flags;
+ int ret;
+
+- ret = smsc95xx_write_reg(dev, INT_STS, INT_STS_CLEAR_ALL_);
+- if (ret < 0)
+- return ret;
+-
+ spin_lock_irqsave(&pdata->mac_cr_lock, flags);
+ if (pdata->phydev->duplex != DUPLEX_FULL) {
+ pdata->mac_cr &= ~MAC_CR_FDPX_;
+--
+2.35.1
+
--- /dev/null
+From e6ed00d71e1b588a2e7f80792c6f3ea5da669da0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 15 Jul 2022 17:15:36 +0200
+Subject: x86/olpc: fix 'logical not is only applied to the left hand side'
+
+From: Alexander Lobakin <alexandr.lobakin@intel.com>
+
+[ Upstream commit 3a2ba42cbd0b669ce3837ba400905f93dd06c79f ]
+
+The bitops compile-time optimization series revealed one more
+problem in olpc-xo1-sci.c:send_ebook_state(), resulted in GCC
+warnings:
+
+arch/x86/platform/olpc/olpc-xo1-sci.c: In function 'send_ebook_state':
+arch/x86/platform/olpc/olpc-xo1-sci.c:83:63: warning: logical not is only applied to the left hand side of comparison [-Wlogical-not-parentheses]
+ 83 | if (!!test_bit(SW_TABLET_MODE, ebook_switch_idev->sw) == state)
+ | ^~
+arch/x86/platform/olpc/olpc-xo1-sci.c:83:13: note: add parentheses around left hand side expression to silence this warning
+
+Despite this code working as intended, this redundant double
+negation of boolean value, together with comparing to `char`
+with no explicit conversion to bool, makes compilers think
+the author made some unintentional logical mistakes here.
+Make it the other way around and negate the char instead
+to silence the warnings.
+
+Fixes: d2aa37411b8e ("x86/olpc/xo1/sci: Produce wakeup events for buttons and switches")
+Cc: stable@vger.kernel.org # 3.5+
+Reported-by: Guenter Roeck <linux@roeck-us.net>
+Reported-by: kernel test robot <lkp@intel.com>
+Reviewed-and-tested-by: Guenter Roeck <linux@roeck-us.net>
+Signed-off-by: Alexander Lobakin <alexandr.lobakin@intel.com>
+Signed-off-by: Yury Norov <yury.norov@gmail.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ arch/x86/platform/olpc/olpc-xo1-sci.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/arch/x86/platform/olpc/olpc-xo1-sci.c b/arch/x86/platform/olpc/olpc-xo1-sci.c
+index f03a6883dcc6..89f25af4b3c3 100644
+--- a/arch/x86/platform/olpc/olpc-xo1-sci.c
++++ b/arch/x86/platform/olpc/olpc-xo1-sci.c
+@@ -80,7 +80,7 @@ static void send_ebook_state(void)
+ 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);
+--
+2.35.1
+