--- /dev/null
+From stable+bounces-247236-greg=kroah.com@vger.kernel.org Thu May 14 17:55:29 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 11:52:20 -0400
+Subject: block: fix zone write plug removal
+To: stable@vger.kernel.org
+Cc: Damien Le Moal <dlemoal@kernel.org>, Christoph Hellwig <hch@lst.de>, Johannes Thumshirn <johannes.thumshirn@wdc.com>, Jens Axboe <axboe@kernel.dk>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514155220.306649-1-sashal@kernel.org>
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+[ Upstream commit b7d4ffb510373cc6ecf16022dd0e510a023034fb ]
+
+Commit 7b295187287e ("block: Do not remove zone write plugs still in
+use") modified disk_should_remove_zone_wplug() to add a check on the
+reference count of a zone write plug to prevent removing zone write
+plugs from a disk hash table when the plugs are still being referenced
+by BIOs or requests in-flight. However, this check does not take into
+account that a BIO completion may happen right after its submission by
+a zone write plug BIO work, and before the zone write plug BIO work
+releases the zone write plug reference count. This situation leads to
+disk_should_remove_zone_wplug() returning false as in this case the zone
+write plug reference count is at least equal to 3. If the BIO that
+completes in such manner transitioned the zone to the FULL condition,
+the zone write plug for the FULL zone will remain in the disk hash
+table.
+
+Furthermore, relying on a particular value of a zone write plug
+reference count to set the BLK_ZONE_WPLUG_UNHASHED flag is fragile as
+reading the atomic reference count and doing a comparison with some
+value is not overall atomic at all.
+
+Address these issues by reworking the reference counting of zone write
+plugs so that removing plugs from a disk hash table can be done
+directly from disk_put_zone_wplug() when the last reference on a plug
+is dropped.
+
+To do so, replace the function disk_remove_zone_wplug() with
+disk_mark_zone_wplug_dead(). This new function sets the zone write plug
+flag BLK_ZONE_WPLUG_DEAD (which replaces BLK_ZONE_WPLUG_UNHASHED) and
+drops the initial reference on the zone write plug taken when the plug
+was added to the disk hash table. This function is called either for
+zones that are empty or full, or directly in the case of a forced plug
+removal (e.g. when the disk hash table is being destroyed on disk
+removal). With this change, disk_should_remove_zone_wplug() is also
+removed.
+
+disk_put_zone_wplug() is modified to call the function
+disk_free_zone_wplug() to remove a zone write plug from a disk hash
+table and free the plug structure (with a call_rcu()), when the last
+reference on a zone write plug is dropped. disk_free_zone_wplug()
+always checks that the BLK_ZONE_WPLUG_DEAD flag is set.
+
+In order to avoid having multiple zone write plugs for the same zone in
+the disk hash table, disk_get_and_lock_zone_wplug() checked for the
+BLK_ZONE_WPLUG_UNHASHED flag. This check is removed and a check for
+the new BLK_ZONE_WPLUG_DEAD flag is added to
+blk_zone_wplug_handle_write(). With this change, we continue preventing
+adding multiple zone write plugs for the same zone and at the same time
+re-inforce checks on the user behavior by failing new incoming write
+BIOs targeting a zone that is marked as dead. This case can happen only
+if the user erroneously issues write BIOs to zones that are full, or to
+zones that are currently being reset or finished.
+
+Fixes: 7b295187287e ("block: Do not remove zone write plugs still in use")
+Cc: stable@vger.kernel.org
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+[ dropped upstream blk_zone_set_cond() call and disk_zone_wplug_update_cond() context line ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ block/blk-zoned.c | 147 ++++++++++++++++++++----------------------------------
+ 1 file changed, 56 insertions(+), 91 deletions(-)
+
+--- a/block/blk-zoned.c
++++ b/block/blk-zoned.c
+@@ -83,17 +83,17 @@ static inline unsigned int disk_zone_wpl
+ * being executed or the zone write plug bio list is not empty.
+ * - BLK_ZONE_WPLUG_NEED_WP_UPDATE: Indicates that we lost track of a zone
+ * write pointer offset and need to update it.
+- * - BLK_ZONE_WPLUG_UNHASHED: Indicates that the zone write plug was removed
+- * from the disk hash table and that the initial reference to the zone
+- * write plug set when the plug was first added to the hash table has been
+- * dropped. This flag is set when a zone is reset, finished or become full,
+- * to prevent new references to the zone write plug to be taken for
+- * newly incoming BIOs. A zone write plug flagged with this flag will be
+- * freed once all remaining references from BIOs or functions are dropped.
++ * - BLK_ZONE_WPLUG_DEAD: Indicates that the zone write plug will be
++ * removed from the disk hash table of zone write plugs when the last
++ * reference on the zone write plug is dropped. If set, this flag also
++ * indicates that the initial extra reference on the zone write plug was
++ * dropped, meaning that the reference count indicates the current number of
++ * active users (code context or BIOs and requests in flight). This flag is
++ * set when a zone is reset, finished or becomes full.
+ */
+ #define BLK_ZONE_WPLUG_PLUGGED (1U << 0)
+ #define BLK_ZONE_WPLUG_NEED_WP_UPDATE (1U << 1)
+-#define BLK_ZONE_WPLUG_UNHASHED (1U << 2)
++#define BLK_ZONE_WPLUG_DEAD (1U << 2)
+
+ /**
+ * blk_zone_cond_str - Return string XXX in BLK_ZONE_COND_XXX.
+@@ -467,67 +467,42 @@ static void disk_free_zone_wplug_rcu(str
+ mempool_free(zwplug, zwplug->disk->zone_wplugs_pool);
+ }
+
+-static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug)
++static void disk_free_zone_wplug(struct blk_zone_wplug *zwplug)
+ {
+- if (refcount_dec_and_test(&zwplug->ref)) {
+- WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list));
+- WARN_ON_ONCE(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED);
+- WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_UNHASHED));
+-
+- call_rcu(&zwplug->rcu_head, disk_free_zone_wplug_rcu);
+- }
+-}
+-
+-static inline bool disk_should_remove_zone_wplug(struct gendisk *disk,
+- struct blk_zone_wplug *zwplug)
+-{
+- lockdep_assert_held(&zwplug->lock);
+-
+- /* If the zone write plug was already removed, we are done. */
+- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED)
+- return false;
++ struct gendisk *disk = zwplug->disk;
++ unsigned long flags;
+
+- /* If the zone write plug is still plugged, it cannot be removed. */
+- if (zwplug->flags & BLK_ZONE_WPLUG_PLUGGED)
+- return false;
++ WARN_ON_ONCE(!(zwplug->flags & BLK_ZONE_WPLUG_DEAD));
++ WARN_ON_ONCE(zwplug->flags & BLK_ZONE_WPLUG_PLUGGED);
++ WARN_ON_ONCE(!bio_list_empty(&zwplug->bio_list));
+
+- /*
+- * Completions of BIOs with blk_zone_write_plug_bio_endio() may
+- * happen after handling a request completion with
+- * blk_zone_write_plug_finish_request() (e.g. with split BIOs
+- * that are chained). In such case, disk_zone_wplug_unplug_bio()
+- * should not attempt to remove the zone write plug until all BIO
+- * completions are seen. Check by looking at the zone write plug
+- * reference count, which is 2 when the plug is unused (one reference
+- * taken when the plug was allocated and another reference taken by the
+- * caller context).
+- */
+- if (refcount_read(&zwplug->ref) > 2)
+- return false;
++ spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
++ hlist_del_init_rcu(&zwplug->node);
++ atomic_dec(&disk->nr_zone_wplugs);
++ spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+
+- /* We can remove zone write plugs for zones that are empty or full. */
+- return !zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug);
++ call_rcu(&zwplug->rcu_head, disk_free_zone_wplug_rcu);
+ }
+
+-static void disk_remove_zone_wplug(struct gendisk *disk,
+- struct blk_zone_wplug *zwplug)
++static inline void disk_put_zone_wplug(struct blk_zone_wplug *zwplug)
+ {
+- unsigned long flags;
++ if (refcount_dec_and_test(&zwplug->ref))
++ disk_free_zone_wplug(zwplug);
++}
+
+- /* If the zone write plug was already removed, we have nothing to do. */
+- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED)
+- return;
++/*
++ * Flag the zone write plug as dead and drop the initial reference we got when
++ * the zone write plug was added to the hash table. The zone write plug will be
++ * unhashed when its last reference is dropped.
++ */
++static void disk_mark_zone_wplug_dead(struct blk_zone_wplug *zwplug)
++{
++ lockdep_assert_held(&zwplug->lock);
+
+- /*
+- * Mark the zone write plug as unhashed and drop the extra reference we
+- * took when the plug was inserted in the hash table.
+- */
+- zwplug->flags |= BLK_ZONE_WPLUG_UNHASHED;
+- spin_lock_irqsave(&disk->zone_wplugs_lock, flags);
+- hlist_del_init_rcu(&zwplug->node);
+- atomic_dec(&disk->nr_zone_wplugs);
+- spin_unlock_irqrestore(&disk->zone_wplugs_lock, flags);
+- disk_put_zone_wplug(zwplug);
++ if (!(zwplug->flags & BLK_ZONE_WPLUG_DEAD)) {
++ zwplug->flags |= BLK_ZONE_WPLUG_DEAD;
++ disk_put_zone_wplug(zwplug);
++ }
+ }
+
+ static void blk_zone_wplug_bio_work(struct work_struct *work);
+@@ -547,18 +522,7 @@ static struct blk_zone_wplug *disk_get_a
+ again:
+ zwplug = disk_get_zone_wplug(disk, sector);
+ if (zwplug) {
+- /*
+- * Check that a BIO completion or a zone reset or finish
+- * operation has not already removed the zone write plug from
+- * the hash table and dropped its reference count. In such case,
+- * we need to get a new plug so start over from the beginning.
+- */
+ spin_lock_irqsave(&zwplug->lock, *flags);
+- if (zwplug->flags & BLK_ZONE_WPLUG_UNHASHED) {
+- spin_unlock_irqrestore(&zwplug->lock, *flags);
+- disk_put_zone_wplug(zwplug);
+- goto again;
+- }
+ return zwplug;
+ }
+
+@@ -645,14 +609,8 @@ static void disk_zone_wplug_set_wp_offse
+ zwplug->flags &= ~BLK_ZONE_WPLUG_NEED_WP_UPDATE;
+ zwplug->wp_offset = wp_offset;
+ disk_zone_wplug_abort(zwplug);
+-
+- /*
+- * The zone write plug now has no BIO plugged: remove it from the
+- * hash table so that it cannot be seen. The plug will be freed
+- * when the last reference is dropped.
+- */
+- if (disk_should_remove_zone_wplug(disk, zwplug))
+- disk_remove_zone_wplug(disk, zwplug);
++ if (!zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug))
++ disk_mark_zone_wplug_dead(zwplug);
+ }
+
+ static unsigned int blk_zone_wp_offset(struct blk_zone *zone)
+@@ -1068,6 +1026,19 @@ static bool blk_zone_wplug_handle_write(
+ return true;
+ }
+
++ /*
++ * If we got a zone write plug marked as dead, then the user is issuing
++ * writes to a full zone, or without synchronizing with zone reset or
++ * zone finish operations. In such case, fail the BIO to signal this
++ * invalid usage.
++ */
++ if (zwplug->flags & BLK_ZONE_WPLUG_DEAD) {
++ spin_unlock_irqrestore(&zwplug->lock, flags);
++ disk_put_zone_wplug(zwplug);
++ bio_io_error(bio);
++ return true;
++ }
++
+ /* Indicate that this BIO is being handled using zone write plugging. */
+ bio_set_flag(bio, BIO_ZONE_WRITE_PLUGGING);
+
+@@ -1136,7 +1107,7 @@ static void blk_zone_wplug_handle_native
+ disk->disk_name, zwplug->zone_no);
+ disk_zone_wplug_abort(zwplug);
+ }
+- disk_remove_zone_wplug(disk, zwplug);
++ disk_mark_zone_wplug_dead(zwplug);
+ spin_unlock_irqrestore(&zwplug->lock, flags);
+
+ disk_put_zone_wplug(zwplug);
+@@ -1239,14 +1210,8 @@ static void disk_zone_wplug_unplug_bio(s
+ }
+
+ zwplug->flags &= ~BLK_ZONE_WPLUG_PLUGGED;
+-
+- /*
+- * If the zone is full (it was fully written or finished, or empty
+- * (it was reset), remove its zone write plug from the hash table.
+- */
+- if (disk_should_remove_zone_wplug(disk, zwplug))
+- disk_remove_zone_wplug(disk, zwplug);
+-
++ if (!zwplug->wp_offset || disk_zone_wplug_is_full(disk, zwplug))
++ disk_mark_zone_wplug_dead(zwplug);
+ spin_unlock_irqrestore(&zwplug->lock, flags);
+ }
+
+@@ -1457,9 +1422,9 @@ static void disk_destroy_zone_wplugs_has
+ while (!hlist_empty(&disk->zone_wplugs_hash[i])) {
+ zwplug = hlist_entry(disk->zone_wplugs_hash[i].first,
+ struct blk_zone_wplug, node);
+- refcount_inc(&zwplug->ref);
+- disk_remove_zone_wplug(disk, zwplug);
+- disk_put_zone_wplug(zwplug);
++ spin_lock_irq(&zwplug->lock);
++ disk_mark_zone_wplug_dead(zwplug);
++ spin_unlock_irq(&zwplug->lock);
+ }
+ }
+
--- /dev/null
+From stable+bounces-246958-greg=kroah.com@vger.kernel.org Wed May 13 19:37:21 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 13:10:03 -0400
+Subject: Bluetooth: hci_conn: fix potential UAF in create_big_sync
+To: stable@vger.kernel.org
+Cc: David Carlier <devnexen@gmail.com>, Luiz Augusto von Dentz <luiz.von.dentz@intel.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513171003.3829583-1-sashal@kernel.org>
+
+From: David Carlier <devnexen@gmail.com>
+
+[ Upstream commit 0beddb0c380bed5f5b8e61ddbe14635bb73d0b41 ]
+
+Add hci_conn_valid() check in create_big_sync() to detect stale
+connections before proceeding with BIG creation. Handle the
+resulting -ECANCELED in create_big_complete() and re-validate the
+connection under hci_dev_lock() before dereferencing, matching the
+pattern used by create_le_conn_complete() and create_pa_complete().
+
+Keep the hci_conn object alive across the async boundary by taking
+a reference via hci_conn_get() when queueing create_big_sync(), and
+dropping it in the completion callback. The refcount and the lock
+are complementary: the refcount keeps the object allocated, while
+hci_dev_lock() serializes hci_conn_hash_del()'s list_del_rcu() on
+hdev->conn_hash, as required by hci_conn_del().
+
+hci_conn_put() is called outside hci_dev_unlock() so the final put
+(which resolves to kfree() via bt_link_release) does not run under
+hdev->lock, though the release path would be safe either way.
+
+Without this, create_big_complete() would unconditionally
+dereference the conn pointer on error, causing a use-after-free
+via hci_connect_cfm() and hci_conn_del().
+
+Fixes: eca0ae4aea66 ("Bluetooth: Add initial implementation of BIS connections")
+Cc: stable@vger.kernel.org
+Co-developed-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+Signed-off-by: David Carlier <devnexen@gmail.com>
+Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
+[ kept stable's `qos->bcast.out.phy == 0x02` context line instead of upstream's renamed `qos->bcast.out.phys == BIT(1)` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ net/bluetooth/hci_conn.c | 19 ++++++++++++++++++-
+ 1 file changed, 18 insertions(+), 1 deletion(-)
+
+--- a/net/bluetooth/hci_conn.c
++++ b/net/bluetooth/hci_conn.c
+@@ -2113,6 +2113,9 @@ static int create_big_sync(struct hci_de
+ u32 flags = 0;
+ int err;
+
++ if (!hci_conn_valid(hdev, conn))
++ return -ECANCELED;
++
+ if (qos->bcast.out.phy == 0x02)
+ flags |= MGMT_ADV_FLAG_SEC_2M;
+
+@@ -2188,11 +2191,24 @@ static void create_big_complete(struct h
+
+ bt_dev_dbg(hdev, "conn %p", conn);
+
++ if (err == -ECANCELED)
++ goto done;
++
++ hci_dev_lock(hdev);
++
++ if (!hci_conn_valid(hdev, conn))
++ goto unlock;
++
+ if (err) {
+ bt_dev_err(hdev, "Unable to create BIG: %d", err);
+ hci_connect_cfm(conn, err);
+ hci_conn_del(conn);
+ }
++
++unlock:
++ hci_dev_unlock(hdev);
++done:
++ hci_conn_put(conn);
+ }
+
+ struct hci_conn *hci_bind_bis(struct hci_dev *hdev, bdaddr_t *dst, __u8 sid,
+@@ -2309,10 +2325,11 @@ struct hci_conn *hci_connect_bis(struct
+ BT_BOUND, &data);
+
+ /* Queue start periodic advertising and create BIG */
+- err = hci_cmd_sync_queue(hdev, create_big_sync, conn,
++ err = hci_cmd_sync_queue(hdev, create_big_sync, hci_conn_get(conn),
+ create_big_complete);
+ if (err < 0) {
+ hci_conn_drop(conn);
++ hci_conn_put(conn);
+ return ERR_PTR(err);
+ }
+
--- /dev/null
+From e3a6eff92bbd960b471966d9afccb4d584546d17 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Timur=20Krist=C3=B3f?= <timur.kristof@gmail.com>
+Date: Sun, 18 Jan 2026 13:57:46 +0100
+Subject: drm/amdgpu: Fix validating flush_gpu_tlb_pasid()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Timur Kristóf <timur.kristof@gmail.com>
+
+commit e3a6eff92bbd960b471966d9afccb4d584546d17 upstream.
+
+When a function holds a lock and we return without unlocking it,
+it deadlocks the kernel. We should always unlock before returning.
+
+This commit fixes suspend/resume on SI.
+Tested on two Tahiti GPUs: FirePro W9000 and R9 280X.
+
+Fixes: f4db9913e4d3 ("drm/amdgpu: validate the flush_gpu_tlb_pasid()")
+Reported-by: kernel test robot <lkp@intel.com>
+Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
+Closes: https://lore.kernel.org/r/202601190121.z9C0uml5-lkp@intel.com/
+Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
+Signed-off-by: Prike Liang <Prike.Liang@amd.com>
+Reviewed-by: Prike Liang <Prike.Liang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+@@ -738,8 +738,10 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struc
+
+ if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) {
+
+- if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid)
+- return 0;
++ if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid) {
++ r = 0;
++ goto error_unlock_reset;
++ }
+
+ if (adev->gmc.flush_tlb_needs_extra_type_2)
+ adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
--- /dev/null
+From 69c5fbd2b93b5ced77c6e79afe83371bca84c788 Mon Sep 17 00:00:00 2001
+From: Alex Deucher <alexander.deucher@amd.com>
+Date: Mon, 16 Mar 2026 11:04:46 -0400
+Subject: drm/amdgpu: rework how we handle TLB fences
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Alex Deucher <alexander.deucher@amd.com>
+
+commit 69c5fbd2b93b5ced77c6e79afe83371bca84c788 upstream.
+
+Add a new VM flag to indicate whether or not we need
+a TLB fence. Userqs (KFD or KGD) require a TLB fence.
+A TLB fence is not strictly required for kernel queues,
+but it shouldn't hurt. That said, enabling this
+unconditionally should be fine, but it seems to tickle
+some issues in KIQ/MES. Only enable them for KFD,
+or when KGD userq queues are enabled (currently via module
+parameter).
+
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4798
+Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/4749
+Fixes: f3854e04b708 ("drm/amdgpu: attach tlb fence to the PTs update")
+Cc: Christian König <christian.koenig@amd.com>
+Cc: Prike Liang <Prike.Liang@amd.com>
+Reviewed-by: Prike Liang <Prike.Liang@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 7 ++++++-
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 ++
+ 2 files changed, 8 insertions(+), 1 deletion(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -1066,7 +1066,10 @@ amdgpu_vm_tlb_flush(struct amdgpu_vm_upd
+ }
+
+ /* Prepare a TLB flush fence to be attached to PTs */
+- if (!params->unlocked) {
++ /* The check for need_tlb_fence should be dropped once we
++ * sort out the issues with KIQ/MES TLB invalidation timeouts.
++ */
++ if (!params->unlocked && vm->need_tlb_fence) {
+ amdgpu_vm_tlb_fence_create(params->adev, vm, fence);
+
+ /* Makes sure no PD/PT is freed before the flush */
+@@ -2584,6 +2587,7 @@ int amdgpu_vm_init(struct amdgpu_device
+ ttm_lru_bulk_move_init(&vm->lru_bulk_move);
+
+ vm->is_compute_context = false;
++ vm->need_tlb_fence = amdgpu_userq_enabled(&adev->ddev);
+
+ vm->use_cpu_for_update = !!(adev->vm_manager.vm_update_mode &
+ AMDGPU_VM_USE_CPU_FOR_GFX);
+@@ -2721,6 +2725,7 @@ int amdgpu_vm_make_compute(struct amdgpu
+ dma_fence_put(vm->last_update);
+ vm->last_update = dma_fence_get_stub();
+ vm->is_compute_context = true;
++ vm->need_tlb_fence = true;
+
+ unreserve_bo:
+ amdgpu_bo_unreserve(vm->root.bo);
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+@@ -439,6 +439,8 @@ struct amdgpu_vm {
+ struct ttm_lru_bulk_move lru_bulk_move;
+ /* Flag to indicate if VM is used for compute */
+ bool is_compute_context;
++ /* Flag to indicate if VM needs a TLB fence (KFD or KGD) */
++ bool need_tlb_fence;
+
+ /* Memory partition number, -1 means any partition */
+ int8_t mem_id;
--- /dev/null
+From f4db9913e4d3dabe9ff3ea6178f2c1bc286012b8 Mon Sep 17 00:00:00 2001
+From: Prike Liang <Prike.Liang@amd.com>
+Date: Tue, 6 Jan 2026 17:00:57 +0800
+Subject: drm/amdgpu: validate the flush_gpu_tlb_pasid()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Prike Liang <Prike.Liang@amd.com>
+
+commit f4db9913e4d3dabe9ff3ea6178f2c1bc286012b8 upstream.
+
+Validate flush_gpu_tlb_pasid() availability before flushing tlb.
+
+Signed-off-by: Prike Liang <Prike.Liang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gmc.c
+@@ -737,6 +737,10 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struc
+ return 0;
+
+ if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) {
++
++ if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid)
++ return 0;
++
+ if (adev->gmc.flush_tlb_needs_extra_type_2)
+ adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
+ 2, all_hub,
--- /dev/null
+From stable+bounces-247237-greg=kroah.com@vger.kernel.org Thu May 14 17:52:38 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 11:52:31 -0400
+Subject: EDAC/versalnet: Fix device name memory leak
+To: stable@vger.kernel.org
+Cc: Prasanna Kumar T S M <ptsm@linux.microsoft.com>, "Borislav Petkov (AMD)" <bp@alien8.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514155232.307214-1-sashal@kernel.org>
+
+From: Prasanna Kumar T S M <ptsm@linux.microsoft.com>
+
+[ Upstream commit 8cf5dd235eff6008cb04c3d8064d2acfa90616f1 ]
+
+The device name allocated via kzalloc() in init_one_mc() is assigned to
+dev->init_name but never freed on the normal removal path. device_register()
+copies init_name and then sets dev->init_name to NULL, so the name pointer
+becomes unreachable from the device. Thus leaking memory.
+
+Use a stack-local char array instead of using kzalloc() for name.
+
+Fixes: d5fe2fec6c40 ("EDAC: Add a driver for the AMD Versal NET DDR controller")
+Signed-off-by: Prasanna Kumar T S M <ptsm@linux.microsoft.com>
+Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de>
+Cc: stable@vger.kernel.org
+Link: https://patch.msgid.link/20260401111856.2342975-1-ptsm@linux.microsoft.com
+[ adapted fix from `init_one_mc()` helper to the equivalent loop in `init_versalnet()` using literal `32` instead of `MC_NAME_LEN` ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/edac/versalnet_edac.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/edac/versalnet_edac.c
++++ b/drivers/edac/versalnet_edac.c
+@@ -765,9 +765,9 @@ static int init_versalnet(struct mc_priv
+ u32 num_chans, rank, dwidth, config;
+ struct edac_mc_layer layers[2];
+ struct mem_ctl_info *mci;
++ char name[32];
+ struct device *dev;
+ enum dev_type dt;
+- char *name;
+ int rc, i;
+
+ for (i = 0; i < NUM_CONTROLLERS; i++) {
+@@ -814,7 +814,6 @@ static int init_versalnet(struct mc_priv
+
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ dev->release = versal_edac_release;
+- name = kmalloc(32, GFP_KERNEL);
+ sprintf(name, "versal-net-ddrmc5-edac-%d", i);
+ dev->init_name = name;
+ rc = device_register(dev);
--- /dev/null
+From stable+bounces-247267-greg=kroah.com@vger.kernel.org Thu May 14 19:58:56 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 13:58:45 -0400
+Subject: fbcon: Avoid OOB font access if console rotation fails
+To: stable@vger.kernel.org
+Cc: Thomas Zimmermann <tzimmermann@suse.de>, Helge Deller <deller@gmx.de>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514175845.529279-2-sashal@kernel.org>
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit e4ef723d8975a2694cc90733a6b888a5e2841842 ]
+
+Clear the font buffer if the reallocation during console rotation fails
+in fbcon_rotate_font(). The putcs implementations for the rotated buffer
+will return early in this case. See [1] for an example.
+
+Currently, fbcon_rotate_font() keeps the old buffer, which is too small
+for the rotated font. Printing to the rotated console with a high-enough
+character code will overflow the font buffer.
+
+v2:
+- fix typos in commit message
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Fixes: 6cc50e1c5b57 ("[PATCH] fbcon: Console Rotation - Add support to rotate font bitmap")
+Cc: stable@vger.kernel.org # v2.6.15+
+Link: https://elixir.bootlin.com/linux/v6.19/source/drivers/video/fbdev/core/fbcon_ccw.c#L144 # [1]
+Signed-off-by: Helge Deller <deller@gmx.de>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/video/fbdev/core/fbcon_rotate.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/video/fbdev/core/fbcon_rotate.c
++++ b/drivers/video/fbdev/core/fbcon_rotate.c
+@@ -46,6 +46,10 @@ static int fbcon_rotate_font(struct fb_i
+ info->fbops->fb_sync(info);
+
+ if (par->fd_size < d_cellsize * len) {
++ kfree(par->fontbuffer);
++ par->fontbuffer = NULL;
++ par->fd_size = 0;
++
+ dst = kmalloc_array(len, d_cellsize, GFP_KERNEL);
+
+ if (dst == NULL) {
+@@ -54,7 +58,6 @@ static int fbcon_rotate_font(struct fb_i
+ }
+
+ par->fd_size = d_cellsize * len;
+- kfree(par->fontbuffer);
+ par->fontbuffer = dst;
+ }
+
--- /dev/null
+From stable+bounces-247266-greg=kroah.com@vger.kernel.org Thu May 14 19:58:52 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 13:58:44 -0400
+Subject: fbcon: Rename struct fbcon_ops to struct fbcon_par
+To: stable@vger.kernel.org
+Cc: Thomas Zimmermann <tzimmermann@suse.de>, Sam Ravnborg <sam@ravnborg.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514175845.529279-1-sashal@kernel.org>
+
+From: Thomas Zimmermann <tzimmermann@suse.de>
+
+[ Upstream commit a6adbbc4c32a016146e117b1e9e5242724a75e10 ]
+
+The type struct fbcon_ops contains fbcon state and callbacks. As the
+callbacks will be removed from struct fbcon_ops, rename the data type
+to struct fbcon_par. Also rename the variables from ops to par.
+
+The _par postfix ("private access registers") is used throughout the
+fbdev subsystem for per-driver state. The fbcon pointer within struct
+fb_info is also named fbcon_par. Hence, the new naming fits existing
+practice.
+
+v2:
+- rename struct fbcon_ops to struct fbcon_par
+- fix build for CONFIG_FB_TILEBITTING=n (kernel test robot)
+- fix indention
+
+Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
+Reviewed-by: Sam Ravnborg <sam@ravnborg.org>
+Link: https://lore.kernel.org/r/20250909124616.143365-3-tzimmermann@suse.de
+Stable-dep-of: e4ef723d8975 ("fbcon: Avoid OOB font access if console rotation fails")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/video/fbdev/core/bitblit.c | 120 ++++-----
+ drivers/video/fbdev/core/fbcon.c | 419 +++++++++++++++-----------------
+ drivers/video/fbdev/core/fbcon.h | 6
+ drivers/video/fbdev/core/fbcon_ccw.c | 146 +++++------
+ drivers/video/fbdev/core/fbcon_cw.c | 146 +++++------
+ drivers/video/fbdev/core/fbcon_rotate.c | 40 +--
+ drivers/video/fbdev/core/fbcon_rotate.h | 6
+ drivers/video/fbdev/core/fbcon_ud.c | 162 ++++++------
+ drivers/video/fbdev/core/softcursor.c | 20 -
+ drivers/video/fbdev/core/tileblit.c | 28 +-
+ 10 files changed, 541 insertions(+), 552 deletions(-)
+
+--- a/drivers/video/fbdev/core/bitblit.c
++++ b/drivers/video/fbdev/core/bitblit.c
+@@ -261,10 +261,10 @@ static void bit_cursor(struct vc_data *v
+ int fg, int bg)
+ {
+ struct fb_cursor cursor;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ int w = DIV_ROUND_UP(vc->vc_font.width, 8), c;
+- int y = real_y(ops->p, vc->state.y);
++ int y = real_y(par->p, vc->state.y);
+ int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
+ int err = 1;
+ char *src;
+@@ -278,10 +278,10 @@ static void bit_cursor(struct vc_data *v
+ attribute = get_attribute(info, c);
+ src = vc->vc_font.data + ((c & charmask) * (w * vc->vc_font.height));
+
+- if (ops->cursor_state.image.data != src ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.data = src;
+- cursor.set |= FB_CUR_SETIMAGE;
++ if (par->cursor_state.image.data != src ||
++ par->cursor_reset) {
++ par->cursor_state.image.data = src;
++ cursor.set |= FB_CUR_SETIMAGE;
+ }
+
+ if (attribute) {
+@@ -290,46 +290,46 @@ static void bit_cursor(struct vc_data *v
+ dst = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
+ if (!dst)
+ return;
+- kfree(ops->cursor_data);
+- ops->cursor_data = dst;
++ kfree(par->cursor_data);
++ par->cursor_data = dst;
+ update_attr(dst, src, attribute, vc);
+ src = dst;
+ }
+
+- if (ops->cursor_state.image.fg_color != fg ||
+- ops->cursor_state.image.bg_color != bg ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.fg_color = fg;
+- ops->cursor_state.image.bg_color = bg;
++ if (par->cursor_state.image.fg_color != fg ||
++ par->cursor_state.image.bg_color != bg ||
++ par->cursor_reset) {
++ par->cursor_state.image.fg_color = fg;
++ par->cursor_state.image.bg_color = bg;
+ cursor.set |= FB_CUR_SETCMAP;
+ }
+
+- if ((ops->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) ||
+- (ops->cursor_state.image.dy != (vc->vc_font.height * y)) ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.dx = vc->vc_font.width * vc->state.x;
+- ops->cursor_state.image.dy = vc->vc_font.height * y;
++ if ((par->cursor_state.image.dx != (vc->vc_font.width * vc->state.x)) ||
++ (par->cursor_state.image.dy != (vc->vc_font.height * y)) ||
++ par->cursor_reset) {
++ par->cursor_state.image.dx = vc->vc_font.width * vc->state.x;
++ par->cursor_state.image.dy = vc->vc_font.height * y;
+ cursor.set |= FB_CUR_SETPOS;
+ }
+
+- if (ops->cursor_state.image.height != vc->vc_font.height ||
+- ops->cursor_state.image.width != vc->vc_font.width ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.height = vc->vc_font.height;
+- ops->cursor_state.image.width = vc->vc_font.width;
++ if (par->cursor_state.image.height != vc->vc_font.height ||
++ par->cursor_state.image.width != vc->vc_font.width ||
++ par->cursor_reset) {
++ par->cursor_state.image.height = vc->vc_font.height;
++ par->cursor_state.image.width = vc->vc_font.width;
+ cursor.set |= FB_CUR_SETSIZE;
+ }
+
+- if (ops->cursor_state.hot.x || ops->cursor_state.hot.y ||
+- ops->cursor_reset) {
+- ops->cursor_state.hot.x = cursor.hot.y = 0;
++ if (par->cursor_state.hot.x || par->cursor_state.hot.y ||
++ par->cursor_reset) {
++ par->cursor_state.hot.x = cursor.hot.y = 0;
+ cursor.set |= FB_CUR_SETHOT;
+ }
+
+ if (cursor.set & FB_CUR_SETSIZE ||
+- vc->vc_cursor_type != ops->p->cursor_shape ||
+- ops->cursor_state.mask == NULL ||
+- ops->cursor_reset) {
++ vc->vc_cursor_type != par->p->cursor_shape ||
++ par->cursor_state.mask == NULL ||
++ par->cursor_reset) {
+ char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
+ int cur_height, size, i = 0;
+ u8 msk = 0xff;
+@@ -337,13 +337,13 @@ static void bit_cursor(struct vc_data *v
+ if (!mask)
+ return;
+
+- kfree(ops->cursor_state.mask);
+- ops->cursor_state.mask = mask;
++ kfree(par->cursor_state.mask);
++ par->cursor_state.mask = mask;
+
+- ops->p->cursor_shape = vc->vc_cursor_type;
++ par->p->cursor_shape = vc->vc_cursor_type;
+ cursor.set |= FB_CUR_SETSHAPE;
+
+- switch (CUR_SIZE(ops->p->cursor_shape)) {
++ switch (CUR_SIZE(par->p->cursor_shape)) {
+ case CUR_NONE:
+ cur_height = 0;
+ break;
+@@ -372,19 +372,19 @@ static void bit_cursor(struct vc_data *v
+ mask[i++] = msk;
+ }
+
+- ops->cursor_state.enable = enable && !use_sw;
++ par->cursor_state.enable = enable && !use_sw;
+
+ cursor.image.data = src;
+- cursor.image.fg_color = ops->cursor_state.image.fg_color;
+- cursor.image.bg_color = ops->cursor_state.image.bg_color;
+- cursor.image.dx = ops->cursor_state.image.dx;
+- cursor.image.dy = ops->cursor_state.image.dy;
+- cursor.image.height = ops->cursor_state.image.height;
+- cursor.image.width = ops->cursor_state.image.width;
+- cursor.hot.x = ops->cursor_state.hot.x;
+- cursor.hot.y = ops->cursor_state.hot.y;
+- cursor.mask = ops->cursor_state.mask;
+- cursor.enable = ops->cursor_state.enable;
++ cursor.image.fg_color = par->cursor_state.image.fg_color;
++ cursor.image.bg_color = par->cursor_state.image.bg_color;
++ cursor.image.dx = par->cursor_state.image.dx;
++ cursor.image.dy = par->cursor_state.image.dy;
++ cursor.image.height = par->cursor_state.image.height;
++ cursor.image.width = par->cursor_state.image.width;
++ cursor.hot.x = par->cursor_state.hot.x;
++ cursor.hot.y = par->cursor_state.hot.y;
++ cursor.mask = par->cursor_state.mask;
++ cursor.enable = par->cursor_state.enable;
+ cursor.image.depth = 1;
+ cursor.rop = ROP_XOR;
+
+@@ -394,31 +394,31 @@ static void bit_cursor(struct vc_data *v
+ if (err)
+ soft_cursor(info, &cursor);
+
+- ops->cursor_reset = 0;
++ par->cursor_reset = 0;
+ }
+
+ static int bit_update_start(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int err;
+
+- err = fb_pan_display(info, &ops->var);
+- ops->var.xoffset = info->var.xoffset;
+- ops->var.yoffset = info->var.yoffset;
+- ops->var.vmode = info->var.vmode;
++ err = fb_pan_display(info, &par->var);
++ par->var.xoffset = info->var.xoffset;
++ par->var.yoffset = info->var.yoffset;
++ par->var.vmode = info->var.vmode;
+ return err;
+ }
+
+-void fbcon_set_bitops(struct fbcon_ops *ops)
++void fbcon_set_bitops(struct fbcon_par *par)
+ {
+- ops->bmove = bit_bmove;
+- ops->clear = bit_clear;
+- ops->putcs = bit_putcs;
+- ops->clear_margins = bit_clear_margins;
+- ops->cursor = bit_cursor;
+- ops->update_start = bit_update_start;
+- ops->rotate_font = NULL;
++ par->bmove = bit_bmove;
++ par->clear = bit_clear;
++ par->putcs = bit_putcs;
++ par->clear_margins = bit_clear_margins;
++ par->cursor = bit_cursor;
++ par->update_start = bit_update_start;
++ par->rotate_font = NULL;
+
+- if (ops->rotate)
+- fbcon_set_rotate(ops);
++ if (par->rotate)
++ fbcon_set_rotate(par);
+ }
+--- a/drivers/video/fbdev/core/fbcon.c
++++ b/drivers/video/fbdev/core/fbcon.c
+@@ -200,27 +200,27 @@ static struct device *fbcon_device;
+ #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
+ static inline void fbcon_set_rotation(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ if (!(info->flags & FBINFO_MISC_TILEBLITTING) &&
+- ops->p->con_rotate < 4)
+- ops->rotate = ops->p->con_rotate;
++ par->p->con_rotate < 4)
++ par->rotate = par->p->con_rotate;
+ else
+- ops->rotate = 0;
++ par->rotate = 0;
+ }
+
+ static void fbcon_rotate(struct fb_info *info, u32 rotate)
+ {
+- struct fbcon_ops *ops= info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fb_info *fb_info;
+
+- if (!ops || ops->currcon == -1)
++ if (!par || par->currcon == -1)
+ return;
+
+- fb_info = fbcon_info_from_console(ops->currcon);
++ fb_info = fbcon_info_from_console(par->currcon);
+
+ if (info == fb_info) {
+- struct fbcon_display *p = &fb_display[ops->currcon];
++ struct fbcon_display *p = &fb_display[par->currcon];
+
+ if (rotate < 4)
+ p->con_rotate = rotate;
+@@ -233,12 +233,12 @@ static void fbcon_rotate(struct fb_info
+
+ static void fbcon_rotate_all(struct fb_info *info, u32 rotate)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct vc_data *vc;
+ struct fbcon_display *p;
+ int i;
+
+- if (!ops || ops->currcon < 0 || rotate > 3)
++ if (!par || par->currcon < 0 || rotate > 3)
+ return;
+
+ for (i = first_fb_vc; i <= last_fb_vc; i++) {
+@@ -256,9 +256,9 @@ static void fbcon_rotate_all(struct fb_i
+ #else
+ static inline void fbcon_set_rotation(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+- ops->rotate = FB_ROTATE_UR;
++ par->rotate = FB_ROTATE_UR;
+ }
+
+ static void fbcon_rotate(struct fb_info *info, u32 rotate)
+@@ -274,9 +274,9 @@ static void fbcon_rotate_all(struct fb_i
+
+ static int fbcon_get_rotate(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+- return (ops) ? ops->rotate : 0;
++ return (par) ? par->rotate : 0;
+ }
+
+ static bool fbcon_skip_panic(struct fb_info *info)
+@@ -286,10 +286,10 @@ static bool fbcon_skip_panic(struct fb_i
+
+ static inline bool fbcon_is_active(struct vc_data *vc, struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ return info->state == FBINFO_STATE_RUNNING &&
+- vc->vc_mode == KD_TEXT && !ops->graphics && !fbcon_skip_panic(info);
++ vc->vc_mode == KD_TEXT && !par->graphics && !fbcon_skip_panic(info);
+ }
+
+ static int get_color(struct vc_data *vc, struct fb_info *info,
+@@ -371,7 +371,7 @@ static int get_bg_color(struct vc_data *
+
+ static void fb_flashcursor(struct work_struct *work)
+ {
+- struct fbcon_ops *ops = container_of(work, struct fbcon_ops, cursor_work.work);
++ struct fbcon_par *par = container_of(work, struct fbcon_par, cursor_work.work);
+ struct fb_info *info;
+ struct vc_data *vc = NULL;
+ int c;
+@@ -386,10 +386,10 @@ static void fb_flashcursor(struct work_s
+ return;
+
+ /* protected by console_lock */
+- info = ops->info;
++ info = par->info;
+
+- if (ops->currcon != -1)
+- vc = vc_cons[ops->currcon].d;
++ if (par->currcon != -1)
++ vc = vc_cons[par->currcon].d;
+
+ if (!vc || !con_is_visible(vc) ||
+ fbcon_info_from_console(vc->vc_num) != info ||
+@@ -399,30 +399,30 @@ static void fb_flashcursor(struct work_s
+ }
+
+ c = scr_readw((u16 *) vc->vc_pos);
+- enable = ops->cursor_flash && !ops->cursor_state.enable;
+- ops->cursor(vc, info, enable,
++ enable = par->cursor_flash && !par->cursor_state.enable;
++ par->cursor(vc, info, enable,
+ get_fg_color(vc, info, c),
+ get_bg_color(vc, info, c));
+ console_unlock();
+
+- queue_delayed_work(system_power_efficient_wq, &ops->cursor_work,
+- ops->cur_blink_jiffies);
++ queue_delayed_work(system_power_efficient_wq, &par->cursor_work,
++ par->cur_blink_jiffies);
+ }
+
+ static void fbcon_add_cursor_work(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ if (fbcon_cursor_blink)
+- queue_delayed_work(system_power_efficient_wq, &ops->cursor_work,
+- ops->cur_blink_jiffies);
++ queue_delayed_work(system_power_efficient_wq, &par->cursor_work,
++ par->cur_blink_jiffies);
+ }
+
+ static void fbcon_del_cursor_work(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+- cancel_delayed_work_sync(&ops->cursor_work);
++ cancel_delayed_work_sync(&par->cursor_work);
+ }
+
+ #ifndef MODULE
+@@ -582,7 +582,7 @@ static void fbcon_prepare_logo(struct vc
+ int cols, int rows, int new_cols, int new_rows)
+ {
+ /* Need to make room for the logo */
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int cnt, erase = vc->vc_video_erase_char, step;
+ unsigned short *save = NULL, *r, *q;
+ int logo_height;
+@@ -598,7 +598,7 @@ static void fbcon_prepare_logo(struct vc
+ */
+ if (fb_get_color_depth(&info->var, &info->fix) == 1)
+ erase &= ~0x400;
+- logo_height = fb_prepare_logo(info, ops->rotate);
++ logo_height = fb_prepare_logo(info, par->rotate);
+ logo_lines = DIV_ROUND_UP(logo_height, vc->vc_font.height);
+ q = (unsigned short *) (vc->vc_origin +
+ vc->vc_size_row * rows);
+@@ -670,15 +670,15 @@ static void fbcon_prepare_logo(struct vc
+ #ifdef CONFIG_FB_TILEBLITTING
+ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+- ops->p = &fb_display[vc->vc_num];
++ par->p = &fb_display[vc->vc_num];
+
+ if ((info->flags & FBINFO_MISC_TILEBLITTING))
+ fbcon_set_tileops(vc, info);
+ else {
+ fbcon_set_rotation(info);
+- fbcon_set_bitops(ops);
++ fbcon_set_bitops(par);
+ }
+ }
+
+@@ -695,12 +695,12 @@ static int fbcon_invalid_charcount(struc
+ #else
+ static void set_blitting_type(struct vc_data *vc, struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ info->flags &= ~FBINFO_MISC_TILEBLITTING;
+- ops->p = &fb_display[vc->vc_num];
++ par->p = &fb_display[vc->vc_num];
+ fbcon_set_rotation(info);
+- fbcon_set_bitops(ops);
++ fbcon_set_bitops(par);
+ }
+
+ static int fbcon_invalid_charcount(struct fb_info *info, unsigned charcount)
+@@ -720,13 +720,13 @@ static void fbcon_release(struct fb_info
+ module_put(info->fbops->owner);
+
+ if (info->fbcon_par) {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ fbcon_del_cursor_work(info);
+- kfree(ops->cursor_state.mask);
+- kfree(ops->cursor_data);
+- kfree(ops->cursor_src);
+- kfree(ops->fontbuffer);
++ kfree(par->cursor_state.mask);
++ kfree(par->cursor_data);
++ kfree(par->cursor_src);
++ kfree(par->fontbuffer);
+ kfree(info->fbcon_par);
+ info->fbcon_par = NULL;
+ }
+@@ -734,7 +734,7 @@ static void fbcon_release(struct fb_info
+
+ static int fbcon_open(struct fb_info *info)
+ {
+- struct fbcon_ops *ops;
++ struct fbcon_par *par;
+
+ if (!try_module_get(info->fbops->owner))
+ return -ENODEV;
+@@ -748,16 +748,16 @@ static int fbcon_open(struct fb_info *in
+ }
+ unlock_fb_info(info);
+
+- ops = kzalloc(sizeof(struct fbcon_ops), GFP_KERNEL);
+- if (!ops) {
++ par = kzalloc(sizeof(*par), GFP_KERNEL);
++ if (!par) {
+ fbcon_release(info);
+ return -ENOMEM;
+ }
+
+- INIT_DELAYED_WORK(&ops->cursor_work, fb_flashcursor);
+- ops->info = info;
+- info->fbcon_par = ops;
+- ops->cur_blink_jiffies = HZ / 5;
++ INIT_DELAYED_WORK(&par->cursor_work, fb_flashcursor);
++ par->info = info;
++ info->fbcon_par = par;
++ par->cur_blink_jiffies = HZ / 5;
+
+ return 0;
+ }
+@@ -804,12 +804,12 @@ static void con2fb_release_oldinfo(struc
+ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
+ int unit, int show_logo)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int ret;
+
+- ops->currcon = fg_console;
++ par->currcon = fg_console;
+
+- if (info->fbops->fb_set_par && !ops->initialized) {
++ if (info->fbops->fb_set_par && !par->initialized) {
+ ret = info->fbops->fb_set_par(info);
+
+ if (ret)
+@@ -818,8 +818,8 @@ static void con2fb_init_display(struct v
+ "error code %d\n", ret);
+ }
+
+- ops->initialized = true;
+- ops->graphics = 0;
++ par->initialized = true;
++ par->graphics = 0;
+ fbcon_set_disp(info, &info->var, unit);
+
+ if (show_logo) {
+@@ -956,7 +956,7 @@ static const char *fbcon_startup(void)
+ struct vc_data *vc = vc_cons[fg_console].d;
+ const struct font_desc *font = NULL;
+ struct fb_info *info = NULL;
+- struct fbcon_ops *ops;
++ struct fbcon_par *par;
+ int rows, cols;
+
+ /*
+@@ -976,10 +976,10 @@ static const char *fbcon_startup(void)
+ if (fbcon_open(info))
+ return NULL;
+
+- ops = info->fbcon_par;
+- ops->currcon = -1;
+- ops->graphics = 1;
+- ops->cur_rotate = -1;
++ par = info->fbcon_par;
++ par->currcon = -1;
++ par->graphics = 1;
++ par->cur_rotate = -1;
+
+ p->con_rotate = initial_rotation;
+ if (p->con_rotate == -1)
+@@ -1002,8 +1002,8 @@ static const char *fbcon_startup(void)
+ vc->vc_font.charcount = font->charcount;
+ }
+
+- cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
+- rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
++ cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
++ rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
+ cols /= vc->vc_font.width;
+ rows /= vc->vc_font.height;
+ vc_resize(vc, cols, rows);
+@@ -1021,7 +1021,7 @@ static const char *fbcon_startup(void)
+ static void fbcon_init(struct vc_data *vc, bool init)
+ {
+ struct fb_info *info;
+- struct fbcon_ops *ops;
++ struct fbcon_par *par;
+ struct vc_data **default_mode = vc->vc_display_fg;
+ struct vc_data *svc = *default_mode;
+ struct fbcon_display *t, *p = &fb_display[vc->vc_num];
+@@ -1096,8 +1096,8 @@ static void fbcon_init(struct vc_data *v
+ if (!*vc->uni_pagedict_loc)
+ con_copy_unimap(vc, svc);
+
+- ops = info->fbcon_par;
+- ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
++ par = info->fbcon_par;
++ par->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
+
+ p->con_rotate = initial_rotation;
+ if (p->con_rotate == -1)
+@@ -1109,8 +1109,8 @@ static void fbcon_init(struct vc_data *v
+
+ cols = vc->vc_cols;
+ rows = vc->vc_rows;
+- new_cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
+- new_rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
++ new_cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
++ new_rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
+ new_cols /= vc->vc_font.width;
+ new_rows /= vc->vc_font.height;
+
+@@ -1122,7 +1122,7 @@ static void fbcon_init(struct vc_data *v
+ * We need to do it in fbcon_init() to prevent screen corruption.
+ */
+ if (con_is_visible(vc) && vc->vc_mode == KD_TEXT) {
+- if (info->fbops->fb_set_par && !ops->initialized) {
++ if (info->fbops->fb_set_par && !par->initialized) {
+ ret = info->fbops->fb_set_par(info);
+
+ if (ret)
+@@ -1131,10 +1131,10 @@ static void fbcon_init(struct vc_data *v
+ "error code %d\n", ret);
+ }
+
+- ops->initialized = true;
++ par->initialized = true;
+ }
+
+- ops->graphics = 0;
++ par->graphics = 0;
+
+ #ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
+ if ((info->flags & FBINFO_HWACCEL_COPYAREA) &&
+@@ -1158,12 +1158,12 @@ static void fbcon_init(struct vc_data *v
+ if (logo)
+ fbcon_prepare_logo(vc, info, cols, rows, new_cols, new_rows);
+
+- if (ops->rotate_font && ops->rotate_font(info, vc)) {
+- ops->rotate = FB_ROTATE_UR;
++ if (par->rotate_font && par->rotate_font(info, vc)) {
++ par->rotate = FB_ROTATE_UR;
+ set_blitting_type(vc, info);
+ }
+
+- ops->p = &fb_display[fg_console];
++ par->p = &fb_display[fg_console];
+ }
+
+ static void fbcon_free_font(struct fbcon_display *p)
+@@ -1201,7 +1201,7 @@ static void fbcon_deinit(struct vc_data
+ {
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+ struct fb_info *info;
+- struct fbcon_ops *ops;
++ struct fbcon_par *par;
+ int idx;
+
+ fbcon_free_font(p);
+@@ -1215,15 +1215,15 @@ static void fbcon_deinit(struct vc_data
+ if (!info)
+ goto finished;
+
+- ops = info->fbcon_par;
++ par = info->fbcon_par;
+
+- if (!ops)
++ if (!par)
+ goto finished;
+
+ if (con_is_visible(vc))
+ fbcon_del_cursor_work(info);
+
+- ops->initialized = false;
++ par->initialized = false;
+ finished:
+
+ fbcon_free_font(p);
+@@ -1270,7 +1270,7 @@ static void __fbcon_clear(struct vc_data
+ unsigned int height, unsigned int width)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int fg, bg;
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+ u_int y_break;
+@@ -1285,7 +1285,7 @@ static void __fbcon_clear(struct vc_data
+ vc->vc_top = 0;
+ /*
+ * If the font dimensions are not an integral of the display
+- * dimensions then the ops->clear below won't end up clearing
++ * dimensions then the par->clear below won't end up clearing
+ * the margins. Call clear_margins here in case the logo
+ * bitmap stretched into the margin area.
+ */
+@@ -1299,11 +1299,10 @@ static void __fbcon_clear(struct vc_data
+ y_break = p->vrows - p->yscroll;
+ if (sy < y_break && sy + height - 1 >= y_break) {
+ u_int b = y_break - sy;
+- ops->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg);
+- ops->clear(vc, info, real_y(p, sy + b), sx, height - b,
+- width, fg, bg);
++ par->clear(vc, info, real_y(p, sy), sx, b, width, fg, bg);
++ par->clear(vc, info, real_y(p, sy + b), sx, height - b, width, fg, bg);
+ } else
+- ops->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg);
++ par->clear(vc, info, real_y(p, sy), sx, height, width, fg, bg);
+ }
+
+ static void fbcon_clear(struct vc_data *vc, unsigned int sy, unsigned int sx,
+@@ -1317,10 +1316,10 @@ static void fbcon_putcs(struct vc_data *
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ if (fbcon_is_active(vc, info))
+- ops->putcs(vc, info, s, count, real_y(p, ypos), xpos,
++ par->putcs(vc, info, s, count, real_y(p, ypos), xpos,
+ get_fg_color(vc, info, scr_readw(s)),
+ get_bg_color(vc, info, scr_readw(s)));
+ }
+@@ -1328,19 +1327,19 @@ static void fbcon_putcs(struct vc_data *
+ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ if (fbcon_is_active(vc, info))
+- ops->clear_margins(vc, info, margin_color, bottom_only);
++ par->clear_margins(vc, info, margin_color, bottom_only);
+ }
+
+ static void fbcon_cursor(struct vc_data *vc, bool enable)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int c = scr_readw((u16 *) vc->vc_pos);
+
+- ops->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
++ par->cur_blink_jiffies = msecs_to_jiffies(vc->vc_cur_blink_ms);
+
+ if (!fbcon_is_active(vc, info) || vc->vc_deccm != 1)
+ return;
+@@ -1350,12 +1349,12 @@ static void fbcon_cursor(struct vc_data
+ else
+ fbcon_add_cursor_work(info);
+
+- ops->cursor_flash = enable;
++ par->cursor_flash = enable;
+
+- if (!ops->cursor)
++ if (!par->cursor)
+ return;
+
+- ops->cursor(vc, info, enable,
++ par->cursor(vc, info, enable,
+ get_fg_color(vc, info, c),
+ get_bg_color(vc, info, c));
+ }
+@@ -1370,7 +1369,7 @@ static void fbcon_set_disp(struct fb_inf
+ struct fbcon_display *p, *t;
+ struct vc_data **default_mode, *vc;
+ struct vc_data *svc;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int rows, cols;
+ unsigned long ret = 0;
+
+@@ -1403,7 +1402,7 @@ static void fbcon_set_disp(struct fb_inf
+ var->yoffset = info->var.yoffset;
+ var->xoffset = info->var.xoffset;
+ fb_set_var(info, var);
+- ops->var = info->var;
++ par->var = info->var;
+ vc->vc_can_do_color = (fb_get_color_depth(&info->var, &info->fix)!=1);
+ vc->vc_complement_mask = vc->vc_can_do_color ? 0x7700 : 0x0800;
+ if (vc->vc_font.charcount == 256) {
+@@ -1419,8 +1418,8 @@ static void fbcon_set_disp(struct fb_inf
+ if (!*vc->uni_pagedict_loc)
+ con_copy_unimap(vc, svc);
+
+- cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
+- rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
++ cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
++ rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
+ cols /= vc->vc_font.width;
+ rows /= vc->vc_font.height;
+ ret = vc_resize(vc, cols, rows);
+@@ -1432,16 +1431,16 @@ static void fbcon_set_disp(struct fb_inf
+ static __inline__ void ywrap_up(struct vc_data *vc, int count)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+
+ p->yscroll += count;
+ if (p->yscroll >= p->vrows) /* Deal with wrap */
+ p->yscroll -= p->vrows;
+- ops->var.xoffset = 0;
+- ops->var.yoffset = p->yscroll * vc->vc_font.height;
+- ops->var.vmode |= FB_VMODE_YWRAP;
+- ops->update_start(info);
++ par->var.xoffset = 0;
++ par->var.yoffset = p->yscroll * vc->vc_font.height;
++ par->var.vmode |= FB_VMODE_YWRAP;
++ par->update_start(info);
+ scrollback_max += count;
+ if (scrollback_max > scrollback_phys_max)
+ scrollback_max = scrollback_phys_max;
+@@ -1451,16 +1450,16 @@ static __inline__ void ywrap_up(struct v
+ static __inline__ void ywrap_down(struct vc_data *vc, int count)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+
+ p->yscroll -= count;
+ if (p->yscroll < 0) /* Deal with wrap */
+ p->yscroll += p->vrows;
+- ops->var.xoffset = 0;
+- ops->var.yoffset = p->yscroll * vc->vc_font.height;
+- ops->var.vmode |= FB_VMODE_YWRAP;
+- ops->update_start(info);
++ par->var.xoffset = 0;
++ par->var.yoffset = p->yscroll * vc->vc_font.height;
++ par->var.vmode |= FB_VMODE_YWRAP;
++ par->update_start(info);
+ scrollback_max -= count;
+ if (scrollback_max < 0)
+ scrollback_max = 0;
+@@ -1471,19 +1470,19 @@ static __inline__ void ypan_up(struct vc
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ p->yscroll += count;
+ if (p->yscroll > p->vrows - vc->vc_rows) {
+- ops->bmove(vc, info, p->vrows - vc->vc_rows,
++ par->bmove(vc, info, p->vrows - vc->vc_rows,
+ 0, 0, 0, vc->vc_rows, vc->vc_cols);
+ p->yscroll -= p->vrows - vc->vc_rows;
+ }
+
+- ops->var.xoffset = 0;
+- ops->var.yoffset = p->yscroll * vc->vc_font.height;
+- ops->var.vmode &= ~FB_VMODE_YWRAP;
+- ops->update_start(info);
++ par->var.xoffset = 0;
++ par->var.yoffset = p->yscroll * vc->vc_font.height;
++ par->var.vmode &= ~FB_VMODE_YWRAP;
++ par->update_start(info);
+ fbcon_clear_margins(vc, 1);
+ scrollback_max += count;
+ if (scrollback_max > scrollback_phys_max)
+@@ -1494,7 +1493,7 @@ static __inline__ void ypan_up(struct vc
+ static __inline__ void ypan_up_redraw(struct vc_data *vc, int t, int count)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+
+ p->yscroll += count;
+@@ -1504,10 +1503,10 @@ static __inline__ void ypan_up_redraw(st
+ fbcon_redraw_move(vc, p, t + count, vc->vc_rows - count, t);
+ }
+
+- ops->var.xoffset = 0;
+- ops->var.yoffset = p->yscroll * vc->vc_font.height;
+- ops->var.vmode &= ~FB_VMODE_YWRAP;
+- ops->update_start(info);
++ par->var.xoffset = 0;
++ par->var.yoffset = p->yscroll * vc->vc_font.height;
++ par->var.vmode &= ~FB_VMODE_YWRAP;
++ par->update_start(info);
+ fbcon_clear_margins(vc, 1);
+ scrollback_max += count;
+ if (scrollback_max > scrollback_phys_max)
+@@ -1519,19 +1518,19 @@ static __inline__ void ypan_down(struct
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ p->yscroll -= count;
+ if (p->yscroll < 0) {
+- ops->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows,
++ par->bmove(vc, info, 0, 0, p->vrows - vc->vc_rows,
+ 0, vc->vc_rows, vc->vc_cols);
+ p->yscroll += p->vrows - vc->vc_rows;
+ }
+
+- ops->var.xoffset = 0;
+- ops->var.yoffset = p->yscroll * vc->vc_font.height;
+- ops->var.vmode &= ~FB_VMODE_YWRAP;
+- ops->update_start(info);
++ par->var.xoffset = 0;
++ par->var.yoffset = p->yscroll * vc->vc_font.height;
++ par->var.vmode &= ~FB_VMODE_YWRAP;
++ par->update_start(info);
+ fbcon_clear_margins(vc, 1);
+ scrollback_max -= count;
+ if (scrollback_max < 0)
+@@ -1542,7 +1541,7 @@ static __inline__ void ypan_down(struct
+ static __inline__ void ypan_down_redraw(struct vc_data *vc, int t, int count)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+
+ p->yscroll -= count;
+@@ -1552,10 +1551,10 @@ static __inline__ void ypan_down_redraw(
+ fbcon_redraw_move(vc, p, t, vc->vc_rows - count, t + count);
+ }
+
+- ops->var.xoffset = 0;
+- ops->var.yoffset = p->yscroll * vc->vc_font.height;
+- ops->var.vmode &= ~FB_VMODE_YWRAP;
+- ops->update_start(info);
++ par->var.xoffset = 0;
++ par->var.yoffset = p->yscroll * vc->vc_font.height;
++ par->var.vmode &= ~FB_VMODE_YWRAP;
++ par->update_start(info);
+ fbcon_clear_margins(vc, 1);
+ scrollback_max -= count;
+ if (scrollback_max < 0)
+@@ -1604,7 +1603,7 @@ static void fbcon_redraw_blit(struct vc_
+ unsigned short *d = (unsigned short *)
+ (vc->vc_origin + vc->vc_size_row * line);
+ unsigned short *s = d + offset;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ while (count--) {
+ unsigned short *start = s;
+@@ -1617,8 +1616,8 @@ static void fbcon_redraw_blit(struct vc_
+
+ if (c == scr_readw(d)) {
+ if (s > start) {
+- ops->bmove(vc, info, line + ycount, x,
+- line, x, 1, s-start);
++ par->bmove(vc, info, line + ycount, x,
++ line, x, 1, s - start);
+ x += s - start + 1;
+ start = s + 1;
+ } else {
+@@ -1633,8 +1632,7 @@ static void fbcon_redraw_blit(struct vc_
+ d++;
+ } while (s < le);
+ if (s > start)
+- ops->bmove(vc, info, line + ycount, x, line, x, 1,
+- s-start);
++ par->bmove(vc, info, line + ycount, x, line, x, 1, s - start);
+ console_conditional_schedule();
+ if (ycount > 0)
+ line++;
+@@ -1705,7 +1703,7 @@ static void fbcon_bmove_rec(struct vc_da
+ int dy, int dx, int height, int width, u_int y_break)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ u_int b;
+
+ if (sy < y_break && sy + height > y_break) {
+@@ -1739,8 +1737,7 @@ static void fbcon_bmove_rec(struct vc_da
+ }
+ return;
+ }
+- ops->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx,
+- height, width);
++ par->bmove(vc, info, real_y(p, sy), sx, real_y(p, dy), dx, height, width);
+ }
+
+ static void fbcon_bmove(struct vc_data *vc, int sy, int sx, int dy, int dx,
+@@ -1967,15 +1964,13 @@ static void updatescrollmode_accel(struc
+ struct vc_data *vc)
+ {
+ #ifdef CONFIG_FRAMEBUFFER_CONSOLE_LEGACY_ACCELERATION
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int cap = info->flags;
+ u16 t = 0;
+- int ypan = FBCON_SWAP(ops->rotate, info->fix.ypanstep,
+- info->fix.xpanstep);
+- int ywrap = FBCON_SWAP(ops->rotate, info->fix.ywrapstep, t);
+- int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+- int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
+- info->var.xres_virtual);
++ int ypan = FBCON_SWAP(par->rotate, info->fix.ypanstep, info->fix.xpanstep);
++ int ywrap = FBCON_SWAP(par->rotate, info->fix.ywrapstep, t);
++ int yres = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
++ int vyres = FBCON_SWAP(par->rotate, info->var.yres_virtual, info->var.xres_virtual);
+ int good_pan = (cap & FBINFO_HWACCEL_YPAN) &&
+ divides(ypan, vc->vc_font.height) && vyres > yres;
+ int good_wrap = (cap & FBINFO_HWACCEL_YWRAP) &&
+@@ -2008,11 +2003,10 @@ static void updatescrollmode(struct fbco
+ struct fb_info *info,
+ struct vc_data *vc)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int fh = vc->vc_font.height;
+- int yres = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
+- int vyres = FBCON_SWAP(ops->rotate, info->var.yres_virtual,
+- info->var.xres_virtual);
++ int yres = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
++ int vyres = FBCON_SWAP(par->rotate, info->var.yres_virtual, info->var.xres_virtual);
+
+ p->vrows = vyres/fh;
+ if (yres > (fh * (vc->vc_rows + 1)))
+@@ -2031,7 +2025,7 @@ static int fbcon_resize(struct vc_data *
+ unsigned int height, bool from_user)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+ struct fb_var_screeninfo var = info->var;
+ int x_diff, y_diff, virt_w, virt_h, virt_fw, virt_fh;
+@@ -2054,12 +2048,10 @@ static int fbcon_resize(struct vc_data *
+ return -EINVAL;
+ }
+
+- virt_w = FBCON_SWAP(ops->rotate, width, height);
+- virt_h = FBCON_SWAP(ops->rotate, height, width);
+- virt_fw = FBCON_SWAP(ops->rotate, vc->vc_font.width,
+- vc->vc_font.height);
+- virt_fh = FBCON_SWAP(ops->rotate, vc->vc_font.height,
+- vc->vc_font.width);
++ virt_w = FBCON_SWAP(par->rotate, width, height);
++ virt_h = FBCON_SWAP(par->rotate, height, width);
++ virt_fw = FBCON_SWAP(par->rotate, vc->vc_font.width, vc->vc_font.height);
++ virt_fh = FBCON_SWAP(par->rotate, vc->vc_font.height, vc->vc_font.width);
+ var.xres = virt_w * virt_fw;
+ var.yres = virt_h * virt_fh;
+ x_diff = info->var.xres - var.xres;
+@@ -2085,7 +2077,7 @@ static int fbcon_resize(struct vc_data *
+ fb_set_var(info, &var);
+ }
+ var_to_display(p, &info->var, info);
+- ops->var = info->var;
++ par->var = info->var;
+ }
+ updatescrollmode(p, info, vc);
+ return 0;
+@@ -2094,13 +2086,13 @@ static int fbcon_resize(struct vc_data *
+ static bool fbcon_switch(struct vc_data *vc)
+ {
+ struct fb_info *info, *old_info = NULL;
+- struct fbcon_ops *ops;
++ struct fbcon_par *par;
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+ struct fb_var_screeninfo var;
+ int i, ret, prev_console;
+
+ info = fbcon_info_from_console(vc->vc_num);
+- ops = info->fbcon_par;
++ par = info->fbcon_par;
+
+ if (logo_shown >= 0) {
+ struct vc_data *conp2 = vc_cons[logo_shown].d;
+@@ -2111,7 +2103,7 @@ static bool fbcon_switch(struct vc_data
+ logo_shown = FBCON_LOGO_CANSHOW;
+ }
+
+- prev_console = ops->currcon;
++ prev_console = par->currcon;
+ if (prev_console != -1)
+ old_info = fbcon_info_from_console(prev_console);
+ /*
+@@ -2124,9 +2116,9 @@ static bool fbcon_switch(struct vc_data
+ */
+ fbcon_for_each_registered_fb(i) {
+ if (fbcon_registered_fb[i]->fbcon_par) {
+- struct fbcon_ops *o = fbcon_registered_fb[i]->fbcon_par;
++ struct fbcon_par *par = fbcon_registered_fb[i]->fbcon_par;
+
+- o->currcon = vc->vc_num;
++ par->currcon = vc->vc_num;
+ }
+ }
+ memset(&var, 0, sizeof(struct fb_var_screeninfo));
+@@ -2140,7 +2132,7 @@ static bool fbcon_switch(struct vc_data
+ info->var.activate = var.activate;
+ var.vmode |= info->var.vmode & ~FB_VMODE_MASK;
+ fb_set_var(info, &var);
+- ops->var = info->var;
++ par->var = info->var;
+
+ if (old_info != NULL && (old_info != info ||
+ info->flags & FBINFO_MISC_ALWAYS_SETPAR)) {
+@@ -2157,17 +2149,16 @@ static bool fbcon_switch(struct vc_data
+ fbcon_del_cursor_work(old_info);
+ }
+
+- if (!fbcon_is_active(vc, info) ||
+- ops->blank_state != FB_BLANK_UNBLANK)
++ if (!fbcon_is_active(vc, info) || par->blank_state != FB_BLANK_UNBLANK)
+ fbcon_del_cursor_work(info);
+ else
+ fbcon_add_cursor_work(info);
+
+ set_blitting_type(vc, info);
+- ops->cursor_reset = 1;
++ par->cursor_reset = 1;
+
+- if (ops->rotate_font && ops->rotate_font(info, vc)) {
+- ops->rotate = FB_ROTATE_UR;
++ if (par->rotate_font && par->rotate_font(info, vc)) {
++ par->rotate = FB_ROTATE_UR;
+ set_blitting_type(vc, info);
+ }
+
+@@ -2198,8 +2189,8 @@ static bool fbcon_switch(struct vc_data
+ scrollback_current = 0;
+
+ if (fbcon_is_active(vc, info)) {
+- ops->var.xoffset = ops->var.yoffset = p->yscroll = 0;
+- ops->update_start(info);
++ par->var.xoffset = par->var.yoffset = p->yscroll = 0;
++ par->update_start(info);
+ }
+
+ fbcon_set_palette(vc, color_table);
+@@ -2208,7 +2199,7 @@ static bool fbcon_switch(struct vc_data
+ if (logo_shown == FBCON_LOGO_DRAW) {
+
+ logo_shown = fg_console;
+- fb_show_logo(info, ops->rotate);
++ fb_show_logo(info, par->rotate);
+ update_region(vc,
+ vc->vc_origin + vc->vc_size_row * vc->vc_top,
+ vc->vc_size_row * (vc->vc_bottom -
+@@ -2237,27 +2228,27 @@ static bool fbcon_blank(struct vc_data *
+ bool mode_switch)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+ if (mode_switch) {
+ struct fb_var_screeninfo var = info->var;
+
+- ops->graphics = 1;
++ par->graphics = 1;
+
+ if (!blank) {
+ var.activate = FB_ACTIVATE_NOW | FB_ACTIVATE_FORCE |
+ FB_ACTIVATE_KD_TEXT;
+ fb_set_var(info, &var);
+- ops->graphics = 0;
+- ops->var = info->var;
++ par->graphics = 0;
++ par->var = info->var;
+ }
+ }
+
+ if (fbcon_is_active(vc, info)) {
+- if (ops->blank_state != blank) {
+- ops->blank_state = blank;
++ if (par->blank_state != blank) {
++ par->blank_state = blank;
+ fbcon_cursor(vc, !blank);
+- ops->cursor_flash = (!blank);
++ par->cursor_flash = (!blank);
+
+ if (fb_blank(info, blank))
+ fbcon_generic_blank(vc, info, blank);
+@@ -2267,8 +2258,7 @@ static bool fbcon_blank(struct vc_data *
+ update_screen(vc);
+ }
+
+- if (mode_switch || !fbcon_is_active(vc, info) ||
+- ops->blank_state != FB_BLANK_UNBLANK)
++ if (mode_switch || !fbcon_is_active(vc, info) || par->blank_state != FB_BLANK_UNBLANK)
+ fbcon_del_cursor_work(info);
+ else
+ fbcon_add_cursor_work(info);
+@@ -2279,10 +2269,10 @@ static bool fbcon_blank(struct vc_data *
+ static void fbcon_debug_enter(struct vc_data *vc)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+- ops->save_graphics = ops->graphics;
+- ops->graphics = 0;
++ par->save_graphics = par->graphics;
++ par->graphics = 0;
+ if (info->fbops->fb_debug_enter)
+ info->fbops->fb_debug_enter(info);
+ fbcon_set_palette(vc, color_table);
+@@ -2291,9 +2281,9 @@ static void fbcon_debug_enter(struct vc_
+ static void fbcon_debug_leave(struct vc_data *vc)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+- ops->graphics = ops->save_graphics;
++ par->graphics = par->save_graphics;
+ if (info->fbops->fb_debug_leave)
+ info->fbops->fb_debug_leave(info);
+ }
+@@ -2428,7 +2418,7 @@ static int fbcon_do_set_font(struct vc_d
+ const u8 * data, int userfont)
+ {
+ struct fb_info *info = fbcon_info_from_console(vc->vc_num);
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fbcon_display *p = &fb_display[vc->vc_num];
+ int resize, ret, old_userfont, old_width, old_height, old_charcount;
+ u8 *old_data = vc->vc_font.data;
+@@ -2454,8 +2444,8 @@ static int fbcon_do_set_font(struct vc_d
+ if (resize) {
+ int cols, rows;
+
+- cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
+- rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
++ cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
++ rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
+ cols /= w;
+ rows /= h;
+ ret = vc_resize(vc, cols, rows);
+@@ -2654,11 +2644,11 @@ static void fbcon_invert_region(struct v
+ void fbcon_suspended(struct fb_info *info)
+ {
+ struct vc_data *vc = NULL;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+- if (!ops || ops->currcon < 0)
++ if (!par || par->currcon < 0)
+ return;
+- vc = vc_cons[ops->currcon].d;
++ vc = vc_cons[par->currcon].d;
+
+ /* Clear cursor, restore saved data */
+ fbcon_cursor(vc, false);
+@@ -2667,27 +2657,27 @@ void fbcon_suspended(struct fb_info *inf
+ void fbcon_resumed(struct fb_info *info)
+ {
+ struct vc_data *vc;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+- if (!ops || ops->currcon < 0)
++ if (!par || par->currcon < 0)
+ return;
+- vc = vc_cons[ops->currcon].d;
++ vc = vc_cons[par->currcon].d;
+
+ update_screen(vc);
+ }
+
+ static void fbcon_modechanged(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct vc_data *vc;
+ struct fbcon_display *p;
+ int rows, cols;
+
+- if (!ops || ops->currcon < 0)
++ if (!par || par->currcon < 0)
+ return;
+- vc = vc_cons[ops->currcon].d;
++ vc = vc_cons[par->currcon].d;
+ if (vc->vc_mode != KD_TEXT ||
+- fbcon_info_from_console(ops->currcon) != info)
++ fbcon_info_from_console(par->currcon) != info)
+ return;
+
+ p = &fb_display[vc->vc_num];
+@@ -2695,8 +2685,8 @@ static void fbcon_modechanged(struct fb_
+
+ if (con_is_visible(vc)) {
+ var_to_display(p, &info->var, info);
+- cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
+- rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
++ cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
++ rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
+ cols /= vc->vc_font.width;
+ rows /= vc->vc_font.height;
+ vc_resize(vc, cols, rows);
+@@ -2705,8 +2695,8 @@ static void fbcon_modechanged(struct fb_
+ scrollback_current = 0;
+
+ if (fbcon_is_active(vc, info)) {
+- ops->var.xoffset = ops->var.yoffset = p->yscroll = 0;
+- ops->update_start(info);
++ par->var.xoffset = par->var.yoffset = p->yscroll = 0;
++ par->update_start(info);
+ }
+
+ fbcon_set_palette(vc, color_table);
+@@ -2716,12 +2706,12 @@ static void fbcon_modechanged(struct fb_
+
+ static void fbcon_set_all_vcs(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct vc_data *vc;
+ struct fbcon_display *p;
+ int i, rows, cols, fg = -1;
+
+- if (!ops || ops->currcon < 0)
++ if (!par || par->currcon < 0)
+ return;
+
+ for (i = first_fb_vc; i <= last_fb_vc; i++) {
+@@ -2738,8 +2728,8 @@ static void fbcon_set_all_vcs(struct fb_
+ p = &fb_display[vc->vc_num];
+ set_blitting_type(vc, info);
+ var_to_display(p, &info->var, info);
+- cols = FBCON_SWAP(ops->rotate, info->var.xres, info->var.yres);
+- rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
++ cols = FBCON_SWAP(par->rotate, info->var.xres, info->var.yres);
++ rows = FBCON_SWAP(par->rotate, info->var.yres, info->var.xres);
+ cols /= vc->vc_font.width;
+ rows /= vc->vc_font.height;
+ vc_resize(vc, cols, rows);
+@@ -2762,13 +2752,13 @@ EXPORT_SYMBOL(fbcon_update_vcs);
+ /* let fbcon check if it supports a new screen resolution */
+ int fbcon_modechange_possible(struct fb_info *info, struct fb_var_screeninfo *var)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct vc_data *vc;
+ unsigned int i;
+
+ WARN_CONSOLE_UNLOCKED();
+
+- if (!ops)
++ if (!par)
+ return 0;
+
+ /* prevent setting a screen size which is smaller than font size */
+@@ -3066,15 +3056,14 @@ int fbcon_fb_registered(struct fb_info *
+
+ void fbcon_fb_blanked(struct fb_info *info, int blank)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct vc_data *vc;
+
+- if (!ops || ops->currcon < 0)
++ if (!par || par->currcon < 0)
+ return;
+
+- vc = vc_cons[ops->currcon].d;
+- if (vc->vc_mode != KD_TEXT ||
+- fbcon_info_from_console(ops->currcon) != info)
++ vc = vc_cons[par->currcon].d;
++ if (vc->vc_mode != KD_TEXT || fbcon_info_from_console(par->currcon) != info)
+ return;
+
+ if (con_is_visible(vc)) {
+@@ -3083,7 +3072,7 @@ void fbcon_fb_blanked(struct fb_info *in
+ else
+ do_unblank_screen(0);
+ }
+- ops->blank_state = blank;
++ par->blank_state = blank;
+ }
+
+ void fbcon_new_modelist(struct fb_info *info)
+@@ -3273,7 +3262,7 @@ static ssize_t cursor_blink_show(struct
+ struct device_attribute *attr, char *buf)
+ {
+ struct fb_info *info;
+- struct fbcon_ops *ops;
++ struct fbcon_par *par;
+ int idx, blink = -1;
+
+ console_lock();
+@@ -3283,12 +3272,12 @@ static ssize_t cursor_blink_show(struct
+ goto err;
+
+ info = fbcon_registered_fb[idx];
+- ops = info->fbcon_par;
++ par = info->fbcon_par;
+
+- if (!ops)
++ if (!par)
+ goto err;
+
+- blink = delayed_work_pending(&ops->cursor_work);
++ blink = delayed_work_pending(&par->cursor_work);
+ err:
+ console_unlock();
+ return sysfs_emit(buf, "%d\n", blink);
+--- a/drivers/video/fbdev/core/fbcon.h
++++ b/drivers/video/fbdev/core/fbcon.h
+@@ -50,7 +50,7 @@ struct fbcon_display {
+ const struct fb_videomode *mode;
+ };
+
+-struct fbcon_ops {
++struct fbcon_par {
+ void (*bmove)(struct vc_data *vc, struct fb_info *info, int sy,
+ int sx, int dy, int dx, int height, int width);
+ void (*clear)(struct vc_data *vc, struct fb_info *info, int sy,
+@@ -185,7 +185,7 @@ static inline u_short fb_scrollmode(stru
+ #ifdef CONFIG_FB_TILEBLITTING
+ extern void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info);
+ #endif
+-extern void fbcon_set_bitops(struct fbcon_ops *ops);
++extern void fbcon_set_bitops(struct fbcon_par *par);
+ extern int soft_cursor(struct fb_info *info, struct fb_cursor *cursor);
+
+ #define FBCON_ATTRIBUTE_UNDERLINE 1
+@@ -224,7 +224,7 @@ static inline int get_attribute(struct f
+ (i == FB_ROTATE_UR || i == FB_ROTATE_UD) ? _r : _v; })
+
+ #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION
+-extern void fbcon_set_rotate(struct fbcon_ops *ops);
++extern void fbcon_set_rotate(struct fbcon_par *par);
+ #else
+ #define fbcon_set_rotate(x) do {} while(0)
+ #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */
+--- a/drivers/video/fbdev/core/fbcon_ccw.c
++++ b/drivers/video/fbdev/core/fbcon_ccw.c
+@@ -63,9 +63,9 @@ static void ccw_update_attr(u8 *dst, u8
+ static void ccw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+ int sx, int dy, int dx, int height, int width)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fb_copyarea area;
+- u32 vyres = GETVYRES(ops->p, info);
++ u32 vyres = GETVYRES(par->p, info);
+
+ area.sx = sy * vc->vc_font.height;
+ area.sy = vyres - ((sx + width) * vc->vc_font.width);
+@@ -80,9 +80,9 @@ static void ccw_bmove(struct vc_data *vc
+ static void ccw_clear(struct vc_data *vc, struct fb_info *info, int sy,
+ int sx, int height, int width, int fg, int bg)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fb_fillrect region;
+- u32 vyres = GETVYRES(ops->p, info);
++ u32 vyres = GETVYRES(par->p, info);
+
+ region.color = bg;
+ region.dx = sy * vc->vc_font.height;
+@@ -99,13 +99,13 @@ static inline void ccw_putcs_aligned(str
+ u32 d_pitch, u32 s_pitch, u32 cellsize,
+ struct fb_image *image, u8 *buf, u8 *dst)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ u32 idx = (vc->vc_font.height + 7) >> 3;
+ u8 *src;
+
+ while (cnt--) {
+- src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize;
++ src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize;
+
+ if (attr) {
+ ccw_update_attr(buf, src, attr, vc);
+@@ -130,7 +130,7 @@ static void ccw_putcs(struct vc_data *vc
+ int fg, int bg)
+ {
+ struct fb_image image;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ u32 width = (vc->vc_font.height + 7)/8;
+ u32 cellsize = width * vc->vc_font.width;
+ u32 maxcnt = info->pixmap.size/cellsize;
+@@ -139,9 +139,9 @@ static void ccw_putcs(struct vc_data *vc
+ u32 cnt, pitch, size;
+ u32 attribute = get_attribute(info, scr_readw(s));
+ u8 *dst, *buf = NULL;
+- u32 vyres = GETVYRES(ops->p, info);
++ u32 vyres = GETVYRES(par->p, info);
+
+- if (!ops->fontbuffer)
++ if (!par->fontbuffer)
+ return;
+
+ image.fg_color = fg;
+@@ -221,28 +221,28 @@ static void ccw_cursor(struct vc_data *v
+ int fg, int bg)
+ {
+ struct fb_cursor cursor;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ int w = (vc->vc_font.height + 7) >> 3, c;
+- int y = real_y(ops->p, vc->state.y);
++ int y = real_y(par->p, vc->state.y);
+ int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
+ int err = 1, dx, dy;
+ char *src;
+- u32 vyres = GETVYRES(ops->p, info);
++ u32 vyres = GETVYRES(par->p, info);
+
+- if (!ops->fontbuffer)
++ if (!par->fontbuffer)
+ return;
+
+ cursor.set = 0;
+
+ c = scr_readw((u16 *) vc->vc_pos);
+ attribute = get_attribute(info, c);
+- src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
++ src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+
+- if (ops->cursor_state.image.data != src ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.data = src;
+- cursor.set |= FB_CUR_SETIMAGE;
++ if (par->cursor_state.image.data != src ||
++ par->cursor_reset) {
++ par->cursor_state.image.data = src;
++ cursor.set |= FB_CUR_SETIMAGE;
+ }
+
+ if (attribute) {
+@@ -251,49 +251,49 @@ static void ccw_cursor(struct vc_data *v
+ dst = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC);
+ if (!dst)
+ return;
+- kfree(ops->cursor_data);
+- ops->cursor_data = dst;
++ kfree(par->cursor_data);
++ par->cursor_data = dst;
+ ccw_update_attr(dst, src, attribute, vc);
+ src = dst;
+ }
+
+- if (ops->cursor_state.image.fg_color != fg ||
+- ops->cursor_state.image.bg_color != bg ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.fg_color = fg;
+- ops->cursor_state.image.bg_color = bg;
++ if (par->cursor_state.image.fg_color != fg ||
++ par->cursor_state.image.bg_color != bg ||
++ par->cursor_reset) {
++ par->cursor_state.image.fg_color = fg;
++ par->cursor_state.image.bg_color = bg;
+ cursor.set |= FB_CUR_SETCMAP;
+ }
+
+- if (ops->cursor_state.image.height != vc->vc_font.width ||
+- ops->cursor_state.image.width != vc->vc_font.height ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.height = vc->vc_font.width;
+- ops->cursor_state.image.width = vc->vc_font.height;
++ if (par->cursor_state.image.height != vc->vc_font.width ||
++ par->cursor_state.image.width != vc->vc_font.height ||
++ par->cursor_reset) {
++ par->cursor_state.image.height = vc->vc_font.width;
++ par->cursor_state.image.width = vc->vc_font.height;
+ cursor.set |= FB_CUR_SETSIZE;
+ }
+
+ dx = y * vc->vc_font.height;
+ dy = vyres - ((vc->state.x + 1) * vc->vc_font.width);
+
+- if (ops->cursor_state.image.dx != dx ||
+- ops->cursor_state.image.dy != dy ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.dx = dx;
+- ops->cursor_state.image.dy = dy;
++ if (par->cursor_state.image.dx != dx ||
++ par->cursor_state.image.dy != dy ||
++ par->cursor_reset) {
++ par->cursor_state.image.dx = dx;
++ par->cursor_state.image.dy = dy;
+ cursor.set |= FB_CUR_SETPOS;
+ }
+
+- if (ops->cursor_state.hot.x || ops->cursor_state.hot.y ||
+- ops->cursor_reset) {
+- ops->cursor_state.hot.x = cursor.hot.y = 0;
++ if (par->cursor_state.hot.x || par->cursor_state.hot.y ||
++ par->cursor_reset) {
++ par->cursor_state.hot.x = cursor.hot.y = 0;
+ cursor.set |= FB_CUR_SETHOT;
+ }
+
+ if (cursor.set & FB_CUR_SETSIZE ||
+- vc->vc_cursor_type != ops->p->cursor_shape ||
+- ops->cursor_state.mask == NULL ||
+- ops->cursor_reset) {
++ vc->vc_cursor_type != par->p->cursor_shape ||
++ par->cursor_state.mask == NULL ||
++ par->cursor_reset) {
+ char *tmp, *mask = kmalloc_array(w, vc->vc_font.width,
+ GFP_ATOMIC);
+ int cur_height, size, i = 0;
+@@ -309,13 +309,13 @@ static void ccw_cursor(struct vc_data *v
+ return;
+ }
+
+- kfree(ops->cursor_state.mask);
+- ops->cursor_state.mask = mask;
++ kfree(par->cursor_state.mask);
++ par->cursor_state.mask = mask;
+
+- ops->p->cursor_shape = vc->vc_cursor_type;
++ par->p->cursor_shape = vc->vc_cursor_type;
+ cursor.set |= FB_CUR_SETSHAPE;
+
+- switch (CUR_SIZE(ops->p->cursor_shape)) {
++ switch (CUR_SIZE(par->p->cursor_shape)) {
+ case CUR_NONE:
+ cur_height = 0;
+ break;
+@@ -348,19 +348,19 @@ static void ccw_cursor(struct vc_data *v
+ kfree(tmp);
+ }
+
+- ops->cursor_state.enable = enable && !use_sw;
++ par->cursor_state.enable = enable && !use_sw;
+
+ cursor.image.data = src;
+- cursor.image.fg_color = ops->cursor_state.image.fg_color;
+- cursor.image.bg_color = ops->cursor_state.image.bg_color;
+- cursor.image.dx = ops->cursor_state.image.dx;
+- cursor.image.dy = ops->cursor_state.image.dy;
+- cursor.image.height = ops->cursor_state.image.height;
+- cursor.image.width = ops->cursor_state.image.width;
+- cursor.hot.x = ops->cursor_state.hot.x;
+- cursor.hot.y = ops->cursor_state.hot.y;
+- cursor.mask = ops->cursor_state.mask;
+- cursor.enable = ops->cursor_state.enable;
++ cursor.image.fg_color = par->cursor_state.image.fg_color;
++ cursor.image.bg_color = par->cursor_state.image.bg_color;
++ cursor.image.dx = par->cursor_state.image.dx;
++ cursor.image.dy = par->cursor_state.image.dy;
++ cursor.image.height = par->cursor_state.image.height;
++ cursor.image.width = par->cursor_state.image.width;
++ cursor.hot.x = par->cursor_state.hot.x;
++ cursor.hot.y = par->cursor_state.hot.y;
++ cursor.mask = par->cursor_state.mask;
++ cursor.enable = par->cursor_state.enable;
+ cursor.image.depth = 1;
+ cursor.rop = ROP_XOR;
+
+@@ -370,32 +370,32 @@ static void ccw_cursor(struct vc_data *v
+ if (err)
+ soft_cursor(info, &cursor);
+
+- ops->cursor_reset = 0;
++ par->cursor_reset = 0;
+ }
+
+ static int ccw_update_start(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ u32 yoffset;
+- u32 vyres = GETVYRES(ops->p, info);
++ u32 vyres = GETVYRES(par->p, info);
+ int err;
+
+- yoffset = (vyres - info->var.yres) - ops->var.xoffset;
+- ops->var.xoffset = ops->var.yoffset;
+- ops->var.yoffset = yoffset;
+- err = fb_pan_display(info, &ops->var);
+- ops->var.xoffset = info->var.xoffset;
+- ops->var.yoffset = info->var.yoffset;
+- ops->var.vmode = info->var.vmode;
++ yoffset = (vyres - info->var.yres) - par->var.xoffset;
++ par->var.xoffset = par->var.yoffset;
++ par->var.yoffset = yoffset;
++ err = fb_pan_display(info, &par->var);
++ par->var.xoffset = info->var.xoffset;
++ par->var.yoffset = info->var.yoffset;
++ par->var.vmode = info->var.vmode;
+ return err;
+ }
+
+-void fbcon_rotate_ccw(struct fbcon_ops *ops)
++void fbcon_rotate_ccw(struct fbcon_par *par)
+ {
+- ops->bmove = ccw_bmove;
+- ops->clear = ccw_clear;
+- ops->putcs = ccw_putcs;
+- ops->clear_margins = ccw_clear_margins;
+- ops->cursor = ccw_cursor;
+- ops->update_start = ccw_update_start;
++ par->bmove = ccw_bmove;
++ par->clear = ccw_clear;
++ par->putcs = ccw_putcs;
++ par->clear_margins = ccw_clear_margins;
++ par->cursor = ccw_cursor;
++ par->update_start = ccw_update_start;
+ }
+--- a/drivers/video/fbdev/core/fbcon_cw.c
++++ b/drivers/video/fbdev/core/fbcon_cw.c
+@@ -48,9 +48,9 @@ static void cw_update_attr(u8 *dst, u8 *
+ static void cw_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+ int sx, int dy, int dx, int height, int width)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fb_copyarea area;
+- u32 vxres = GETVXRES(ops->p, info);
++ u32 vxres = GETVXRES(par->p, info);
+
+ area.sx = vxres - ((sy + height) * vc->vc_font.height);
+ area.sy = sx * vc->vc_font.width;
+@@ -65,9 +65,9 @@ static void cw_bmove(struct vc_data *vc,
+ static void cw_clear(struct vc_data *vc, struct fb_info *info, int sy,
+ int sx, int height, int width, int fg, int bg)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fb_fillrect region;
+- u32 vxres = GETVXRES(ops->p, info);
++ u32 vxres = GETVXRES(par->p, info);
+
+ region.color = bg;
+ region.dx = vxres - ((sy + height) * vc->vc_font.height);
+@@ -84,13 +84,13 @@ static inline void cw_putcs_aligned(stru
+ u32 d_pitch, u32 s_pitch, u32 cellsize,
+ struct fb_image *image, u8 *buf, u8 *dst)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ u32 idx = (vc->vc_font.height + 7) >> 3;
+ u8 *src;
+
+ while (cnt--) {
+- src = ops->fontbuffer + (scr_readw(s++) & charmask)*cellsize;
++ src = par->fontbuffer + (scr_readw(s++) & charmask) * cellsize;
+
+ if (attr) {
+ cw_update_attr(buf, src, attr, vc);
+@@ -115,7 +115,7 @@ static void cw_putcs(struct vc_data *vc,
+ int fg, int bg)
+ {
+ struct fb_image image;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ u32 width = (vc->vc_font.height + 7)/8;
+ u32 cellsize = width * vc->vc_font.width;
+ u32 maxcnt = info->pixmap.size/cellsize;
+@@ -124,9 +124,9 @@ static void cw_putcs(struct vc_data *vc,
+ u32 cnt, pitch, size;
+ u32 attribute = get_attribute(info, scr_readw(s));
+ u8 *dst, *buf = NULL;
+- u32 vxres = GETVXRES(ops->p, info);
++ u32 vxres = GETVXRES(par->p, info);
+
+- if (!ops->fontbuffer)
++ if (!par->fontbuffer)
+ return;
+
+ image.fg_color = fg;
+@@ -204,28 +204,28 @@ static void cw_cursor(struct vc_data *vc
+ int fg, int bg)
+ {
+ struct fb_cursor cursor;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ int w = (vc->vc_font.height + 7) >> 3, c;
+- int y = real_y(ops->p, vc->state.y);
++ int y = real_y(par->p, vc->state.y);
+ int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
+ int err = 1, dx, dy;
+ char *src;
+- u32 vxres = GETVXRES(ops->p, info);
++ u32 vxres = GETVXRES(par->p, info);
+
+- if (!ops->fontbuffer)
++ if (!par->fontbuffer)
+ return;
+
+ cursor.set = 0;
+
+ c = scr_readw((u16 *) vc->vc_pos);
+ attribute = get_attribute(info, c);
+- src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
++ src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.width));
+
+- if (ops->cursor_state.image.data != src ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.data = src;
+- cursor.set |= FB_CUR_SETIMAGE;
++ if (par->cursor_state.image.data != src ||
++ par->cursor_reset) {
++ par->cursor_state.image.data = src;
++ cursor.set |= FB_CUR_SETIMAGE;
+ }
+
+ if (attribute) {
+@@ -234,49 +234,49 @@ static void cw_cursor(struct vc_data *vc
+ dst = kmalloc_array(w, vc->vc_font.width, GFP_ATOMIC);
+ if (!dst)
+ return;
+- kfree(ops->cursor_data);
+- ops->cursor_data = dst;
++ kfree(par->cursor_data);
++ par->cursor_data = dst;
+ cw_update_attr(dst, src, attribute, vc);
+ src = dst;
+ }
+
+- if (ops->cursor_state.image.fg_color != fg ||
+- ops->cursor_state.image.bg_color != bg ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.fg_color = fg;
+- ops->cursor_state.image.bg_color = bg;
++ if (par->cursor_state.image.fg_color != fg ||
++ par->cursor_state.image.bg_color != bg ||
++ par->cursor_reset) {
++ par->cursor_state.image.fg_color = fg;
++ par->cursor_state.image.bg_color = bg;
+ cursor.set |= FB_CUR_SETCMAP;
+ }
+
+- if (ops->cursor_state.image.height != vc->vc_font.width ||
+- ops->cursor_state.image.width != vc->vc_font.height ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.height = vc->vc_font.width;
+- ops->cursor_state.image.width = vc->vc_font.height;
++ if (par->cursor_state.image.height != vc->vc_font.width ||
++ par->cursor_state.image.width != vc->vc_font.height ||
++ par->cursor_reset) {
++ par->cursor_state.image.height = vc->vc_font.width;
++ par->cursor_state.image.width = vc->vc_font.height;
+ cursor.set |= FB_CUR_SETSIZE;
+ }
+
+ dx = vxres - ((y * vc->vc_font.height) + vc->vc_font.height);
+ dy = vc->state.x * vc->vc_font.width;
+
+- if (ops->cursor_state.image.dx != dx ||
+- ops->cursor_state.image.dy != dy ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.dx = dx;
+- ops->cursor_state.image.dy = dy;
++ if (par->cursor_state.image.dx != dx ||
++ par->cursor_state.image.dy != dy ||
++ par->cursor_reset) {
++ par->cursor_state.image.dx = dx;
++ par->cursor_state.image.dy = dy;
+ cursor.set |= FB_CUR_SETPOS;
+ }
+
+- if (ops->cursor_state.hot.x || ops->cursor_state.hot.y ||
+- ops->cursor_reset) {
+- ops->cursor_state.hot.x = cursor.hot.y = 0;
++ if (par->cursor_state.hot.x || par->cursor_state.hot.y ||
++ par->cursor_reset) {
++ par->cursor_state.hot.x = cursor.hot.y = 0;
+ cursor.set |= FB_CUR_SETHOT;
+ }
+
+ if (cursor.set & FB_CUR_SETSIZE ||
+- vc->vc_cursor_type != ops->p->cursor_shape ||
+- ops->cursor_state.mask == NULL ||
+- ops->cursor_reset) {
++ vc->vc_cursor_type != par->p->cursor_shape ||
++ par->cursor_state.mask == NULL ||
++ par->cursor_reset) {
+ char *tmp, *mask = kmalloc_array(w, vc->vc_font.width,
+ GFP_ATOMIC);
+ int cur_height, size, i = 0;
+@@ -292,13 +292,13 @@ static void cw_cursor(struct vc_data *vc
+ return;
+ }
+
+- kfree(ops->cursor_state.mask);
+- ops->cursor_state.mask = mask;
++ kfree(par->cursor_state.mask);
++ par->cursor_state.mask = mask;
+
+- ops->p->cursor_shape = vc->vc_cursor_type;
++ par->p->cursor_shape = vc->vc_cursor_type;
+ cursor.set |= FB_CUR_SETSHAPE;
+
+- switch (CUR_SIZE(ops->p->cursor_shape)) {
++ switch (CUR_SIZE(par->p->cursor_shape)) {
+ case CUR_NONE:
+ cur_height = 0;
+ break;
+@@ -331,19 +331,19 @@ static void cw_cursor(struct vc_data *vc
+ kfree(tmp);
+ }
+
+- ops->cursor_state.enable = enable && !use_sw;
++ par->cursor_state.enable = enable && !use_sw;
+
+ cursor.image.data = src;
+- cursor.image.fg_color = ops->cursor_state.image.fg_color;
+- cursor.image.bg_color = ops->cursor_state.image.bg_color;
+- cursor.image.dx = ops->cursor_state.image.dx;
+- cursor.image.dy = ops->cursor_state.image.dy;
+- cursor.image.height = ops->cursor_state.image.height;
+- cursor.image.width = ops->cursor_state.image.width;
+- cursor.hot.x = ops->cursor_state.hot.x;
+- cursor.hot.y = ops->cursor_state.hot.y;
+- cursor.mask = ops->cursor_state.mask;
+- cursor.enable = ops->cursor_state.enable;
++ cursor.image.fg_color = par->cursor_state.image.fg_color;
++ cursor.image.bg_color = par->cursor_state.image.bg_color;
++ cursor.image.dx = par->cursor_state.image.dx;
++ cursor.image.dy = par->cursor_state.image.dy;
++ cursor.image.height = par->cursor_state.image.height;
++ cursor.image.width = par->cursor_state.image.width;
++ cursor.hot.x = par->cursor_state.hot.x;
++ cursor.hot.y = par->cursor_state.hot.y;
++ cursor.mask = par->cursor_state.mask;
++ cursor.enable = par->cursor_state.enable;
+ cursor.image.depth = 1;
+ cursor.rop = ROP_XOR;
+
+@@ -353,32 +353,32 @@ static void cw_cursor(struct vc_data *vc
+ if (err)
+ soft_cursor(info, &cursor);
+
+- ops->cursor_reset = 0;
++ par->cursor_reset = 0;
+ }
+
+ static int cw_update_start(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
+- u32 vxres = GETVXRES(ops->p, info);
++ struct fbcon_par *par = info->fbcon_par;
++ u32 vxres = GETVXRES(par->p, info);
+ u32 xoffset;
+ int err;
+
+- xoffset = vxres - (info->var.xres + ops->var.yoffset);
+- ops->var.yoffset = ops->var.xoffset;
+- ops->var.xoffset = xoffset;
+- err = fb_pan_display(info, &ops->var);
+- ops->var.xoffset = info->var.xoffset;
+- ops->var.yoffset = info->var.yoffset;
+- ops->var.vmode = info->var.vmode;
++ xoffset = vxres - (info->var.xres + par->var.yoffset);
++ par->var.yoffset = par->var.xoffset;
++ par->var.xoffset = xoffset;
++ err = fb_pan_display(info, &par->var);
++ par->var.xoffset = info->var.xoffset;
++ par->var.yoffset = info->var.yoffset;
++ par->var.vmode = info->var.vmode;
+ return err;
+ }
+
+-void fbcon_rotate_cw(struct fbcon_ops *ops)
++void fbcon_rotate_cw(struct fbcon_par *par)
+ {
+- ops->bmove = cw_bmove;
+- ops->clear = cw_clear;
+- ops->putcs = cw_putcs;
+- ops->clear_margins = cw_clear_margins;
+- ops->cursor = cw_cursor;
+- ops->update_start = cw_update_start;
++ par->bmove = cw_bmove;
++ par->clear = cw_clear;
++ par->putcs = cw_putcs;
++ par->clear_margins = cw_clear_margins;
++ par->cursor = cw_cursor;
++ par->update_start = cw_update_start;
+ }
+--- a/drivers/video/fbdev/core/fbcon_rotate.c
++++ b/drivers/video/fbdev/core/fbcon_rotate.c
+@@ -20,32 +20,32 @@
+
+ static int fbcon_rotate_font(struct fb_info *info, struct vc_data *vc)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int len, err = 0;
+ int s_cellsize, d_cellsize, i;
+ const u8 *src;
+ u8 *dst;
+
+- if (vc->vc_font.data == ops->fontdata &&
+- ops->p->con_rotate == ops->cur_rotate)
++ if (vc->vc_font.data == par->fontdata &&
++ par->p->con_rotate == par->cur_rotate)
+ goto finished;
+
+- src = ops->fontdata = vc->vc_font.data;
+- ops->cur_rotate = ops->p->con_rotate;
++ src = par->fontdata = vc->vc_font.data;
++ par->cur_rotate = par->p->con_rotate;
+ len = vc->vc_font.charcount;
+ s_cellsize = ((vc->vc_font.width + 7)/8) *
+ vc->vc_font.height;
+ d_cellsize = s_cellsize;
+
+- if (ops->rotate == FB_ROTATE_CW ||
+- ops->rotate == FB_ROTATE_CCW)
++ if (par->rotate == FB_ROTATE_CW ||
++ par->rotate == FB_ROTATE_CCW)
+ d_cellsize = ((vc->vc_font.height + 7)/8) *
+ vc->vc_font.width;
+
+ if (info->fbops->fb_sync)
+ info->fbops->fb_sync(info);
+
+- if (ops->fd_size < d_cellsize * len) {
++ if (par->fd_size < d_cellsize * len) {
+ dst = kmalloc_array(len, d_cellsize, GFP_KERNEL);
+
+ if (dst == NULL) {
+@@ -53,15 +53,15 @@ static int fbcon_rotate_font(struct fb_i
+ goto finished;
+ }
+
+- ops->fd_size = d_cellsize * len;
+- kfree(ops->fontbuffer);
+- ops->fontbuffer = dst;
++ par->fd_size = d_cellsize * len;
++ kfree(par->fontbuffer);
++ par->fontbuffer = dst;
+ }
+
+- dst = ops->fontbuffer;
+- memset(dst, 0, ops->fd_size);
++ dst = par->fontbuffer;
++ memset(dst, 0, par->fd_size);
+
+- switch (ops->rotate) {
++ switch (par->rotate) {
+ case FB_ROTATE_UD:
+ for (i = len; i--; ) {
+ rotate_ud(src, dst, vc->vc_font.width,
+@@ -93,19 +93,19 @@ finished:
+ return err;
+ }
+
+-void fbcon_set_rotate(struct fbcon_ops *ops)
++void fbcon_set_rotate(struct fbcon_par *par)
+ {
+- ops->rotate_font = fbcon_rotate_font;
++ par->rotate_font = fbcon_rotate_font;
+
+- switch(ops->rotate) {
++ switch (par->rotate) {
+ case FB_ROTATE_CW:
+- fbcon_rotate_cw(ops);
++ fbcon_rotate_cw(par);
+ break;
+ case FB_ROTATE_UD:
+- fbcon_rotate_ud(ops);
++ fbcon_rotate_ud(par);
+ break;
+ case FB_ROTATE_CCW:
+- fbcon_rotate_ccw(ops);
++ fbcon_rotate_ccw(par);
+ break;
+ }
+ }
+--- a/drivers/video/fbdev/core/fbcon_rotate.h
++++ b/drivers/video/fbdev/core/fbcon_rotate.h
+@@ -90,7 +90,7 @@ static inline void rotate_ccw(const char
+ }
+ }
+
+-extern void fbcon_rotate_cw(struct fbcon_ops *ops);
+-extern void fbcon_rotate_ud(struct fbcon_ops *ops);
+-extern void fbcon_rotate_ccw(struct fbcon_ops *ops);
++extern void fbcon_rotate_cw(struct fbcon_par *par);
++extern void fbcon_rotate_ud(struct fbcon_par *par);
++extern void fbcon_rotate_ccw(struct fbcon_par *par);
+ #endif
+--- a/drivers/video/fbdev/core/fbcon_ud.c
++++ b/drivers/video/fbdev/core/fbcon_ud.c
+@@ -48,10 +48,10 @@ static void ud_update_attr(u8 *dst, u8 *
+ static void ud_bmove(struct vc_data *vc, struct fb_info *info, int sy,
+ int sx, int dy, int dx, int height, int width)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fb_copyarea area;
+- u32 vyres = GETVYRES(ops->p, info);
+- u32 vxres = GETVXRES(ops->p, info);
++ u32 vyres = GETVYRES(par->p, info);
++ u32 vxres = GETVXRES(par->p, info);
+
+ area.sy = vyres - ((sy + height) * vc->vc_font.height);
+ area.sx = vxres - ((sx + width) * vc->vc_font.width);
+@@ -66,10 +66,10 @@ static void ud_bmove(struct vc_data *vc,
+ static void ud_clear(struct vc_data *vc, struct fb_info *info, int sy,
+ int sx, int height, int width, int fg, int bg)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ struct fb_fillrect region;
+- u32 vyres = GETVYRES(ops->p, info);
+- u32 vxres = GETVXRES(ops->p, info);
++ u32 vyres = GETVYRES(par->p, info);
++ u32 vxres = GETVXRES(par->p, info);
+
+ region.color = bg;
+ region.dy = vyres - ((sy + height) * vc->vc_font.height);
+@@ -86,13 +86,13 @@ static inline void ud_putcs_aligned(stru
+ u32 d_pitch, u32 s_pitch, u32 cellsize,
+ struct fb_image *image, u8 *buf, u8 *dst)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ u32 idx = vc->vc_font.width >> 3;
+ u8 *src;
+
+ while (cnt--) {
+- src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize;
++ src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize;
+
+ if (attr) {
+ ud_update_attr(buf, src, attr, vc);
+@@ -119,7 +119,7 @@ static inline void ud_putcs_unaligned(st
+ struct fb_image *image, u8 *buf,
+ u8 *dst)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ u16 charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ u32 shift_low = 0, mod = vc->vc_font.width % 8;
+ u32 shift_high = 8;
+@@ -127,7 +127,7 @@ static inline void ud_putcs_unaligned(st
+ u8 *src;
+
+ while (cnt--) {
+- src = ops->fontbuffer + (scr_readw(s--) & charmask)*cellsize;
++ src = par->fontbuffer + (scr_readw(s--) & charmask) * cellsize;
+
+ if (attr) {
+ ud_update_attr(buf, src, attr, vc);
+@@ -152,7 +152,7 @@ static void ud_putcs(struct vc_data *vc,
+ int fg, int bg)
+ {
+ struct fb_image image;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ u32 width = (vc->vc_font.width + 7)/8;
+ u32 cellsize = width * vc->vc_font.height;
+ u32 maxcnt = info->pixmap.size/cellsize;
+@@ -161,10 +161,10 @@ static void ud_putcs(struct vc_data *vc,
+ u32 mod = vc->vc_font.width % 8, cnt, pitch, size;
+ u32 attribute = get_attribute(info, scr_readw(s));
+ u8 *dst, *buf = NULL;
+- u32 vyres = GETVYRES(ops->p, info);
+- u32 vxres = GETVXRES(ops->p, info);
++ u32 vyres = GETVYRES(par->p, info);
++ u32 vxres = GETVXRES(par->p, info);
+
+- if (!ops->fontbuffer)
++ if (!par->fontbuffer)
+ return;
+
+ image.fg_color = fg;
+@@ -251,29 +251,29 @@ static void ud_cursor(struct vc_data *vc
+ int fg, int bg)
+ {
+ struct fb_cursor cursor;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff;
+ int w = (vc->vc_font.width + 7) >> 3, c;
+- int y = real_y(ops->p, vc->state.y);
++ int y = real_y(par->p, vc->state.y);
+ int attribute, use_sw = vc->vc_cursor_type & CUR_SW;
+ int err = 1, dx, dy;
+ char *src;
+- u32 vyres = GETVYRES(ops->p, info);
+- u32 vxres = GETVXRES(ops->p, info);
++ u32 vyres = GETVYRES(par->p, info);
++ u32 vxres = GETVXRES(par->p, info);
+
+- if (!ops->fontbuffer)
++ if (!par->fontbuffer)
+ return;
+
+ cursor.set = 0;
+
+ c = scr_readw((u16 *) vc->vc_pos);
+ attribute = get_attribute(info, c);
+- src = ops->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
++ src = par->fontbuffer + ((c & charmask) * (w * vc->vc_font.height));
+
+- if (ops->cursor_state.image.data != src ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.data = src;
+- cursor.set |= FB_CUR_SETIMAGE;
++ if (par->cursor_state.image.data != src ||
++ par->cursor_reset) {
++ par->cursor_state.image.data = src;
++ cursor.set |= FB_CUR_SETIMAGE;
+ }
+
+ if (attribute) {
+@@ -282,49 +282,49 @@ static void ud_cursor(struct vc_data *vc
+ dst = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
+ if (!dst)
+ return;
+- kfree(ops->cursor_data);
+- ops->cursor_data = dst;
++ kfree(par->cursor_data);
++ par->cursor_data = dst;
+ ud_update_attr(dst, src, attribute, vc);
+ src = dst;
+ }
+
+- if (ops->cursor_state.image.fg_color != fg ||
+- ops->cursor_state.image.bg_color != bg ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.fg_color = fg;
+- ops->cursor_state.image.bg_color = bg;
++ if (par->cursor_state.image.fg_color != fg ||
++ par->cursor_state.image.bg_color != bg ||
++ par->cursor_reset) {
++ par->cursor_state.image.fg_color = fg;
++ par->cursor_state.image.bg_color = bg;
+ cursor.set |= FB_CUR_SETCMAP;
+ }
+
+- if (ops->cursor_state.image.height != vc->vc_font.height ||
+- ops->cursor_state.image.width != vc->vc_font.width ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.height = vc->vc_font.height;
+- ops->cursor_state.image.width = vc->vc_font.width;
++ if (par->cursor_state.image.height != vc->vc_font.height ||
++ par->cursor_state.image.width != vc->vc_font.width ||
++ par->cursor_reset) {
++ par->cursor_state.image.height = vc->vc_font.height;
++ par->cursor_state.image.width = vc->vc_font.width;
+ cursor.set |= FB_CUR_SETSIZE;
+ }
+
+ dy = vyres - ((y * vc->vc_font.height) + vc->vc_font.height);
+ dx = vxres - ((vc->state.x * vc->vc_font.width) + vc->vc_font.width);
+
+- if (ops->cursor_state.image.dx != dx ||
+- ops->cursor_state.image.dy != dy ||
+- ops->cursor_reset) {
+- ops->cursor_state.image.dx = dx;
+- ops->cursor_state.image.dy = dy;
++ if (par->cursor_state.image.dx != dx ||
++ par->cursor_state.image.dy != dy ||
++ par->cursor_reset) {
++ par->cursor_state.image.dx = dx;
++ par->cursor_state.image.dy = dy;
+ cursor.set |= FB_CUR_SETPOS;
+ }
+
+- if (ops->cursor_state.hot.x || ops->cursor_state.hot.y ||
+- ops->cursor_reset) {
+- ops->cursor_state.hot.x = cursor.hot.y = 0;
++ if (par->cursor_state.hot.x || par->cursor_state.hot.y ||
++ par->cursor_reset) {
++ par->cursor_state.hot.x = cursor.hot.y = 0;
+ cursor.set |= FB_CUR_SETHOT;
+ }
+
+ if (cursor.set & FB_CUR_SETSIZE ||
+- vc->vc_cursor_type != ops->p->cursor_shape ||
+- ops->cursor_state.mask == NULL ||
+- ops->cursor_reset) {
++ vc->vc_cursor_type != par->p->cursor_shape ||
++ par->cursor_state.mask == NULL ||
++ par->cursor_reset) {
+ char *mask = kmalloc_array(w, vc->vc_font.height, GFP_ATOMIC);
+ int cur_height, size, i = 0;
+ u8 msk = 0xff;
+@@ -332,13 +332,13 @@ static void ud_cursor(struct vc_data *vc
+ if (!mask)
+ return;
+
+- kfree(ops->cursor_state.mask);
+- ops->cursor_state.mask = mask;
++ kfree(par->cursor_state.mask);
++ par->cursor_state.mask = mask;
+
+- ops->p->cursor_shape = vc->vc_cursor_type;
++ par->p->cursor_shape = vc->vc_cursor_type;
+ cursor.set |= FB_CUR_SETSHAPE;
+
+- switch (CUR_SIZE(ops->p->cursor_shape)) {
++ switch (CUR_SIZE(par->p->cursor_shape)) {
+ case CUR_NONE:
+ cur_height = 0;
+ break;
+@@ -371,19 +371,19 @@ static void ud_cursor(struct vc_data *vc
+ mask[i++] = ~msk;
+ }
+
+- ops->cursor_state.enable = enable && !use_sw;
++ par->cursor_state.enable = enable && !use_sw;
+
+ cursor.image.data = src;
+- cursor.image.fg_color = ops->cursor_state.image.fg_color;
+- cursor.image.bg_color = ops->cursor_state.image.bg_color;
+- cursor.image.dx = ops->cursor_state.image.dx;
+- cursor.image.dy = ops->cursor_state.image.dy;
+- cursor.image.height = ops->cursor_state.image.height;
+- cursor.image.width = ops->cursor_state.image.width;
+- cursor.hot.x = ops->cursor_state.hot.x;
+- cursor.hot.y = ops->cursor_state.hot.y;
+- cursor.mask = ops->cursor_state.mask;
+- cursor.enable = ops->cursor_state.enable;
++ cursor.image.fg_color = par->cursor_state.image.fg_color;
++ cursor.image.bg_color = par->cursor_state.image.bg_color;
++ cursor.image.dx = par->cursor_state.image.dx;
++ cursor.image.dy = par->cursor_state.image.dy;
++ cursor.image.height = par->cursor_state.image.height;
++ cursor.image.width = par->cursor_state.image.width;
++ cursor.hot.x = par->cursor_state.hot.x;
++ cursor.hot.y = par->cursor_state.hot.y;
++ cursor.mask = par->cursor_state.mask;
++ cursor.enable = par->cursor_state.enable;
+ cursor.image.depth = 1;
+ cursor.rop = ROP_XOR;
+
+@@ -393,36 +393,36 @@ static void ud_cursor(struct vc_data *vc
+ if (err)
+ soft_cursor(info, &cursor);
+
+- ops->cursor_reset = 0;
++ par->cursor_reset = 0;
+ }
+
+ static int ud_update_start(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int xoffset, yoffset;
+- u32 vyres = GETVYRES(ops->p, info);
+- u32 vxres = GETVXRES(ops->p, info);
++ u32 vyres = GETVYRES(par->p, info);
++ u32 vxres = GETVXRES(par->p, info);
+ int err;
+
+- xoffset = vxres - info->var.xres - ops->var.xoffset;
+- yoffset = vyres - info->var.yres - ops->var.yoffset;
++ xoffset = vxres - info->var.xres - par->var.xoffset;
++ yoffset = vyres - info->var.yres - par->var.yoffset;
+ if (yoffset < 0)
+ yoffset += vyres;
+- ops->var.xoffset = xoffset;
+- ops->var.yoffset = yoffset;
+- err = fb_pan_display(info, &ops->var);
+- ops->var.xoffset = info->var.xoffset;
+- ops->var.yoffset = info->var.yoffset;
+- ops->var.vmode = info->var.vmode;
++ par->var.xoffset = xoffset;
++ par->var.yoffset = yoffset;
++ err = fb_pan_display(info, &par->var);
++ par->var.xoffset = info->var.xoffset;
++ par->var.yoffset = info->var.yoffset;
++ par->var.vmode = info->var.vmode;
+ return err;
+ }
+
+-void fbcon_rotate_ud(struct fbcon_ops *ops)
++void fbcon_rotate_ud(struct fbcon_par *par)
+ {
+- ops->bmove = ud_bmove;
+- ops->clear = ud_clear;
+- ops->putcs = ud_putcs;
+- ops->clear_margins = ud_clear_margins;
+- ops->cursor = ud_cursor;
+- ops->update_start = ud_update_start;
++ par->bmove = ud_bmove;
++ par->clear = ud_clear;
++ par->putcs = ud_putcs;
++ par->clear_margins = ud_clear_margins;
++ par->cursor = ud_cursor;
++ par->update_start = ud_update_start;
+ }
+--- a/drivers/video/fbdev/core/softcursor.c
++++ b/drivers/video/fbdev/core/softcursor.c
+@@ -21,7 +21,7 @@
+
+ int soft_cursor(struct fb_info *info, struct fb_cursor *cursor)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ unsigned int scan_align = info->pixmap.scan_align - 1;
+ unsigned int buf_align = info->pixmap.buf_align - 1;
+ unsigned int i, size, dsize, s_pitch, d_pitch;
+@@ -34,19 +34,19 @@ int soft_cursor(struct fb_info *info, st
+ s_pitch = (cursor->image.width + 7) >> 3;
+ dsize = s_pitch * cursor->image.height;
+
+- if (dsize + sizeof(struct fb_image) != ops->cursor_size) {
+- kfree(ops->cursor_src);
+- ops->cursor_size = dsize + sizeof(struct fb_image);
+-
+- ops->cursor_src = kmalloc(ops->cursor_size, GFP_ATOMIC);
+- if (!ops->cursor_src) {
+- ops->cursor_size = 0;
++ if (dsize + sizeof(struct fb_image) != par->cursor_size) {
++ kfree(par->cursor_src);
++ par->cursor_size = dsize + sizeof(struct fb_image);
++
++ par->cursor_src = kmalloc(par->cursor_size, GFP_ATOMIC);
++ if (!par->cursor_src) {
++ par->cursor_size = 0;
+ return -ENOMEM;
+ }
+ }
+
+- src = ops->cursor_src + sizeof(struct fb_image);
+- image = (struct fb_image *)ops->cursor_src;
++ src = par->cursor_src + sizeof(struct fb_image);
++ image = (struct fb_image *)par->cursor_src;
+ *image = cursor->image;
+ d_pitch = (s_pitch + scan_align) & ~scan_align;
+
+--- a/drivers/video/fbdev/core/tileblit.c
++++ b/drivers/video/fbdev/core/tileblit.c
+@@ -151,34 +151,34 @@ static void tile_cursor(struct vc_data *
+
+ static int tile_update_start(struct fb_info *info)
+ {
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+ int err;
+
+- err = fb_pan_display(info, &ops->var);
+- ops->var.xoffset = info->var.xoffset;
+- ops->var.yoffset = info->var.yoffset;
+- ops->var.vmode = info->var.vmode;
++ err = fb_pan_display(info, &par->var);
++ par->var.xoffset = info->var.xoffset;
++ par->var.yoffset = info->var.yoffset;
++ par->var.vmode = info->var.vmode;
+ return err;
+ }
+
+ void fbcon_set_tileops(struct vc_data *vc, struct fb_info *info)
+ {
+ struct fb_tilemap map;
+- struct fbcon_ops *ops = info->fbcon_par;
++ struct fbcon_par *par = info->fbcon_par;
+
+- ops->bmove = tile_bmove;
+- ops->clear = tile_clear;
+- ops->putcs = tile_putcs;
+- ops->clear_margins = tile_clear_margins;
+- ops->cursor = tile_cursor;
+- ops->update_start = tile_update_start;
++ par->bmove = tile_bmove;
++ par->clear = tile_clear;
++ par->putcs = tile_putcs;
++ par->clear_margins = tile_clear_margins;
++ par->cursor = tile_cursor;
++ par->update_start = tile_update_start;
+
+- if (ops->p) {
++ if (par->p) {
+ map.width = vc->vc_font.width;
+ map.height = vc->vc_font.height;
+ map.depth = 1;
+ map.length = vc->vc_font.charcount;
+- map.data = ops->p->fontdata;
++ map.data = par->p->fontdata;
+ info->tileops->fb_settile(info, &map);
+ }
+ }
--- /dev/null
+From 5203012fa6045aac4b69d4e7c212e16dcf38ef10 Mon Sep 17 00:00:00 2001
+From: Xianglai Li <lixianglai@loongson.cn>
+Date: Mon, 4 May 2026 09:00:37 +0800
+Subject: LoongArch: KVM: Compile switch.S directly into the kernel
+
+From: Xianglai Li <lixianglai@loongson.cn>
+
+commit 5203012fa6045aac4b69d4e7c212e16dcf38ef10 upstream.
+
+If we directly compile the switch.S file into the kernel, the address of
+the kvm_exc_entry function will definitely be within the DMW memory area.
+Therefore, we will no longer need to perform a copy relocation of the
+kvm_exc_entry.
+
+So this patch compiles switch.S directly into the kernel, and then remove
+the copy relocation execution logic for the kvm_exc_entry function.
+
+Cc: stable@vger.kernel.org
+Signed-off-by: Xianglai Li <lixianglai@loongson.cn>
+Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/loongarch/Kbuild | 2 -
+ arch/loongarch/include/asm/asm-prototypes.h | 20 ++++++++++++++++
+ arch/loongarch/include/asm/kvm_host.h | 3 --
+ arch/loongarch/kvm/Makefile | 3 +-
+ arch/loongarch/kvm/main.c | 35 ++--------------------------
+ arch/loongarch/kvm/switch.S | 20 ++++++++++++----
+ 6 files changed, 41 insertions(+), 42 deletions(-)
+
+--- a/arch/loongarch/Kbuild
++++ b/arch/loongarch/Kbuild
+@@ -3,7 +3,7 @@ obj-y += mm/
+ obj-y += net/
+ obj-y += vdso/
+
+-obj-$(CONFIG_KVM) += kvm/
++obj-$(subst m,y,$(CONFIG_KVM)) += kvm/
+
+ # for cleaning
+ subdir- += boot
+--- a/arch/loongarch/include/asm/asm-prototypes.h
++++ b/arch/loongarch/include/asm/asm-prototypes.h
+@@ -20,3 +20,23 @@ asmlinkage void noinstr __no_stack_prote
+ struct pt_regs *regs,
+ int (*fn)(void *),
+ void *fn_arg);
++
++struct kvm_run;
++struct kvm_vcpu;
++struct loongarch_fpu;
++
++void kvm_exc_entry(void);
++int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu);
++
++void kvm_save_fpu(struct loongarch_fpu *fpu);
++void kvm_restore_fpu(struct loongarch_fpu *fpu);
++
++#ifdef CONFIG_CPU_HAS_LSX
++void kvm_save_lsx(struct loongarch_fpu *fpu);
++void kvm_restore_lsx(struct loongarch_fpu *fpu);
++#endif
++
++#ifdef CONFIG_CPU_HAS_LASX
++void kvm_save_lasx(struct loongarch_fpu *fpu);
++void kvm_restore_lasx(struct loongarch_fpu *fpu);
++#endif
+--- a/arch/loongarch/include/asm/kvm_host.h
++++ b/arch/loongarch/include/asm/kvm_host.h
+@@ -85,7 +85,6 @@ struct kvm_context {
+ struct kvm_world_switch {
+ int (*exc_entry)(void);
+ int (*enter_guest)(struct kvm_run *run, struct kvm_vcpu *vcpu);
+- unsigned long page_order;
+ };
+
+ #define MAX_PGTABLE_LEVELS 4
+@@ -339,8 +338,6 @@ void kvm_exc_entry(void);
+ int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu);
+
+ extern unsigned long vpid_mask;
+-extern const unsigned long kvm_exception_size;
+-extern const unsigned long kvm_enter_guest_size;
+ extern struct kvm_world_switch *kvm_loongarch_ops;
+
+ #define SW_GCSR (1 << 0)
+--- a/arch/loongarch/kvm/Makefile
++++ b/arch/loongarch/kvm/Makefile
+@@ -7,11 +7,12 @@ include $(srctree)/virt/kvm/Makefile.kvm
+
+ obj-$(CONFIG_KVM) += kvm.o
+
++obj-y += switch.o
++
+ kvm-y += exit.o
+ kvm-y += interrupt.o
+ kvm-y += main.o
+ kvm-y += mmu.o
+-kvm-y += switch.o
+ kvm-y += timer.o
+ kvm-y += tlb.o
+ kvm-y += vcpu.o
+--- a/arch/loongarch/kvm/main.c
++++ b/arch/loongarch/kvm/main.c
+@@ -340,8 +340,7 @@ void kvm_arch_disable_virtualization_cpu
+
+ static int kvm_loongarch_env_init(void)
+ {
+- int cpu, order, ret;
+- void *addr;
++ int cpu, ret;
+ struct kvm_context *context;
+
+ vmcs = alloc_percpu(struct kvm_context);
+@@ -357,30 +356,8 @@ static int kvm_loongarch_env_init(void)
+ return -ENOMEM;
+ }
+
+- /*
+- * PGD register is shared between root kernel and kvm hypervisor.
+- * So world switch entry should be in DMW area rather than TLB area
+- * to avoid page fault reenter.
+- *
+- * In future if hardware pagetable walking is supported, we won't
+- * need to copy world switch code to DMW area.
+- */
+- order = get_order(kvm_exception_size + kvm_enter_guest_size);
+- addr = (void *)__get_free_pages(GFP_KERNEL, order);
+- if (!addr) {
+- free_percpu(vmcs);
+- vmcs = NULL;
+- kfree(kvm_loongarch_ops);
+- kvm_loongarch_ops = NULL;
+- return -ENOMEM;
+- }
+-
+- memcpy(addr, kvm_exc_entry, kvm_exception_size);
+- memcpy(addr + kvm_exception_size, kvm_enter_guest, kvm_enter_guest_size);
+- flush_icache_range((unsigned long)addr, (unsigned long)addr + kvm_exception_size + kvm_enter_guest_size);
+- kvm_loongarch_ops->exc_entry = addr;
+- kvm_loongarch_ops->enter_guest = addr + kvm_exception_size;
+- kvm_loongarch_ops->page_order = order;
++ kvm_loongarch_ops->exc_entry = (void *)kvm_exc_entry;
++ kvm_loongarch_ops->enter_guest = (void *)kvm_enter_guest;
+
+ vpid_mask = read_csr_gstat();
+ vpid_mask = (vpid_mask & CSR_GSTAT_GIDBIT) >> CSR_GSTAT_GIDBIT_SHIFT;
+@@ -414,16 +391,10 @@ static int kvm_loongarch_env_init(void)
+
+ static void kvm_loongarch_env_exit(void)
+ {
+- unsigned long addr;
+-
+ if (vmcs)
+ free_percpu(vmcs);
+
+ if (kvm_loongarch_ops) {
+- if (kvm_loongarch_ops->exc_entry) {
+- addr = (unsigned long)kvm_loongarch_ops->exc_entry;
+- free_pages(addr, kvm_loongarch_ops->page_order);
+- }
+ kfree(kvm_loongarch_ops);
+ }
+
+--- a/arch/loongarch/kvm/switch.S
++++ b/arch/loongarch/kvm/switch.S
+@@ -4,9 +4,11 @@
+ */
+
+ #include <linux/linkage.h>
++#include <linux/kvm_types.h>
+ #include <asm/asm.h>
+ #include <asm/asmmacro.h>
+ #include <asm/loongarch.h>
++#include <asm/page.h>
+ #include <asm/regdef.h>
+ #include <asm/unwind_hints.h>
+
+@@ -100,8 +102,13 @@
+ * - is still in guest mode, such as pgd table/vmid registers etc,
+ * - will fix with hw page walk enabled in future
+ * load kvm_vcpu from reserved CSR KVM_VCPU_KS, and save a2 to KVM_TEMP_KS
++ *
++ * PGD register is shared between root kernel and kvm hypervisor.
++ * So world switch entry should be in DMW area rather than TLB area
++ * to avoid page fault re-enter.
+ */
+ .text
++ .p2align PAGE_SHIFT
+ .cfi_sections .debug_frame
+ SYM_CODE_START(kvm_exc_entry)
+ UNWIND_HINT_END_OF_STACK
+@@ -190,8 +197,8 @@ ret_to_host:
+ kvm_restore_host_gpr a2
+ jr ra
+
+-SYM_INNER_LABEL(kvm_exc_entry_end, SYM_L_LOCAL)
+ SYM_CODE_END(kvm_exc_entry)
++EXPORT_SYMBOL_GPL(kvm_exc_entry)
+
+ /*
+ * int kvm_enter_guest(struct kvm_run *run, struct kvm_vcpu *vcpu)
+@@ -215,8 +222,8 @@ SYM_FUNC_START(kvm_enter_guest)
+ /* Save kvm_vcpu to kscratch */
+ csrwr a1, KVM_VCPU_KS
+ kvm_switch_to_guest
+-SYM_INNER_LABEL(kvm_enter_guest_end, SYM_L_LOCAL)
+ SYM_FUNC_END(kvm_enter_guest)
++EXPORT_SYMBOL_GPL(kvm_enter_guest)
+
+ SYM_FUNC_START(kvm_save_fpu)
+ fpu_save_csr a0 t1
+@@ -224,6 +231,7 @@ SYM_FUNC_START(kvm_save_fpu)
+ fpu_save_cc a0 t1 t2
+ jr ra
+ SYM_FUNC_END(kvm_save_fpu)
++EXPORT_SYMBOL_GPL(kvm_save_fpu)
+
+ SYM_FUNC_START(kvm_restore_fpu)
+ fpu_restore_double a0 t1
+@@ -231,6 +239,7 @@ SYM_FUNC_START(kvm_restore_fpu)
+ fpu_restore_cc a0 t1 t2
+ jr ra
+ SYM_FUNC_END(kvm_restore_fpu)
++EXPORT_SYMBOL_GPL(kvm_restore_fpu)
+
+ #ifdef CONFIG_CPU_HAS_LSX
+ SYM_FUNC_START(kvm_save_lsx)
+@@ -239,6 +248,7 @@ SYM_FUNC_START(kvm_save_lsx)
+ lsx_save_data a0 t1
+ jr ra
+ SYM_FUNC_END(kvm_save_lsx)
++EXPORT_SYMBOL_GPL(kvm_save_lsx)
+
+ SYM_FUNC_START(kvm_restore_lsx)
+ lsx_restore_data a0 t1
+@@ -246,6 +256,7 @@ SYM_FUNC_START(kvm_restore_lsx)
+ fpu_restore_csr a0 t1 t2
+ jr ra
+ SYM_FUNC_END(kvm_restore_lsx)
++EXPORT_SYMBOL_GPL(kvm_restore_lsx)
+ #endif
+
+ #ifdef CONFIG_CPU_HAS_LASX
+@@ -255,6 +266,7 @@ SYM_FUNC_START(kvm_save_lasx)
+ lasx_save_data a0 t1
+ jr ra
+ SYM_FUNC_END(kvm_save_lasx)
++EXPORT_SYMBOL_GPL(kvm_save_lasx)
+
+ SYM_FUNC_START(kvm_restore_lasx)
+ lasx_restore_data a0 t1
+@@ -262,10 +274,8 @@ SYM_FUNC_START(kvm_restore_lasx)
+ fpu_restore_csr a0 t1 t2
+ jr ra
+ SYM_FUNC_END(kvm_restore_lasx)
++EXPORT_SYMBOL_GPL(kvm_restore_lasx)
+ #endif
+- .section ".rodata"
+-SYM_DATA(kvm_exception_size, .quad kvm_exc_entry_end - kvm_exc_entry)
+-SYM_DATA(kvm_enter_guest_size, .quad kvm_enter_guest_end - kvm_enter_guest)
+
+ #ifdef CONFIG_CPU_HAS_LBT
+ STACK_FRAME_NON_STANDARD kvm_restore_fpu
--- /dev/null
+From 8bbde987c2b84f80da0853f739f0a920386f8b99 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Mon, 6 Apr 2026 17:31:52 -0700
+Subject: mm/damon/core: disallow time-quota setting zero esz
+
+From: SeongJae Park <sj@kernel.org>
+
+commit 8bbde987c2b84f80da0853f739f0a920386f8b99 upstream.
+
+When the throughput of a DAMOS scheme is very slow, DAMOS time quota can
+make the effective size quota smaller than damon_ctx->min_region_sz. In
+the case, damos_apply_scheme() will skip applying the action, because the
+action is tried at region level, which requires >=min_region_sz size.
+That is, the quota is effectively exceeded for the quota charge window.
+
+Because no action will be applied, the total_charged_sz and
+total_charged_ns are also not updated. damos_set_effective_quota() will
+try to update the effective size quota before starting the next charge
+window. However, because the total_charged_sz and total_charged_ns have
+not updated, the throughput and effective size quota are also not changed.
+Since effective size quota can only be decreased, other effective size
+quota update factors including DAMOS quota goals and size quota cannot
+make any change, either.
+
+As a result, the scheme is unexpectedly deactivated until the user notices
+and mitigates the situation. The users can mitigate this situation by
+changing the time quota online or re-install the scheme. While the
+mitigation is somewhat straightforward, finding the situation would be
+challenging, because DAMON is not providing good observabilities for that.
+Even if such observability is provided, doing the additional monitoring
+and the mitigation is somewhat cumbersome and not aligned to the intention
+of the time quota. The time quota was intended to help reduce the user's
+administration overhead.
+
+Fix the problem by setting time quota-modified effective size quota be at
+least min_region_sz always.
+
+The issue was discovered [1] by sashiko.
+
+Link: https://lore.kernel.org/20260407003153.79589-1-sj@kernel.org
+Link: https://lore.kernel.org/20260405192504.110014-1-sj@kernel.org [1]
+Fixes: 1cd243030059 ("mm/damon/schemes: implement time quota")
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 5.16.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/core.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+--- a/mm/damon/core.c
++++ b/mm/damon/core.c
+@@ -2135,7 +2135,8 @@ static unsigned long damos_quota_score(s
+ /*
+ * Called only if quota->ms, or quota->sz are set, or quota->goals is not empty
+ */
+-static void damos_set_effective_quota(struct damos_quota *quota)
++static void damos_set_effective_quota(struct damos_quota *quota,
++ struct damon_ctx *ctx)
+ {
+ unsigned long throughput;
+ unsigned long esz = ULONG_MAX;
+@@ -2161,6 +2162,7 @@ static void damos_set_effective_quota(st
+ else
+ throughput = PAGE_SIZE * 1024;
+ esz = min(throughput * quota->ms, esz);
++ esz = max(ctx->min_sz_region, esz);
+ }
+
+ if (quota->sz && quota->sz < esz)
+@@ -2197,7 +2199,7 @@ static void damos_adjust_quota(struct da
+ /* First charge window */
+ if (!quota->total_charged_sz && !quota->charged_from) {
+ quota->charged_from = jiffies;
+- damos_set_effective_quota(quota);
++ damos_set_effective_quota(quota, c);
+ }
+
+ /* New charge window starts */
+@@ -2211,7 +2213,7 @@ static void damos_adjust_quota(struct da
+ quota->charged_sz = 0;
+ if (trace_damos_esz_enabled())
+ cached_esz = quota->esz;
+- damos_set_effective_quota(quota);
++ damos_set_effective_quota(quota, c);
+ if (trace_damos_esz_enabled() && quota->esz != cached_esz)
+ damos_trace_esz(c, s, quota);
+ }
--- /dev/null
+From 4262c53236977de3ceaa3bf2aefdf772c9b874dd Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Thu, 15 Jan 2026 07:20:41 -0800
+Subject: mm/damon/core: implement damon_kdamond_pid()
+
+From: SeongJae Park <sj@kernel.org>
+
+commit 4262c53236977de3ceaa3bf2aefdf772c9b874dd upstream.
+
+Patch series "mm/damon: hide kdamond and kdamond_lock from API callers".
+
+'kdamond' and 'kdamond_lock' fields initially exposed to DAMON API callers
+for flexible synchronization and use cases. As DAMON API became somewhat
+complicated compared to the early days, Keeping those exposed could only
+encourage the API callers to invent more creative but complicated and
+difficult-to-debug use cases.
+
+Fortunately DAMON API callers didn't invent that many creative use cases.
+There exist only two use cases of 'kdamond' and 'kdamond_lock'. Finding
+whether the kdamond is actively running, and getting the pid of the
+kdamond. For the first use case, a dedicated API function, namely
+'damon_is_running()' is provided, and all DAMON API callers are using the
+function for the use case. Hence only the second use case is where the
+fields are directly being used by DAMON API callers.
+
+To prevent future invention of complicated and erroneous use cases of the
+fields, hide the fields from the API callers. For that, provide new
+dedicated DAMON API functions for the remaining use case, namely
+damon_kdamond_pid(), migrate DAMON API callers to use the new function,
+and mark the fields as private fields.
+
+
+This patch (of 5):
+
+'kdamond' and 'kdamond_lock' are directly being used by DAMON API callers
+for getting the pid of the corresponding kdamond. To discourage invention
+of creative but complicated and erroneous new usages of the fields that
+require careful synchronization, implement a new API function that can
+simply be used without the manual synchronizations.
+
+Link: https://lkml.kernel.org/r/20260115152047.68415-1-sj@kernel.org
+Link: https://lkml.kernel.org/r/20260115152047.68415-2-sj@kernel.org
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/damon.h | 1 +
+ mm/damon/core.c | 17 +++++++++++++++++
+ 2 files changed, 18 insertions(+)
+
+--- a/include/linux/damon.h
++++ b/include/linux/damon.h
+@@ -949,6 +949,7 @@ bool damon_initialized(void);
+ int damon_start(struct damon_ctx **ctxs, int nr_ctxs, bool exclusive);
+ int damon_stop(struct damon_ctx **ctxs, int nr_ctxs);
+ bool damon_is_running(struct damon_ctx *ctx);
++int damon_kdamond_pid(struct damon_ctx *ctx);
+
+ int damon_call(struct damon_ctx *ctx, struct damon_call_control *control);
+ int damos_walk(struct damon_ctx *ctx, struct damos_walk_control *control);
+--- a/mm/damon/core.c
++++ b/mm/damon/core.c
+@@ -1437,6 +1437,23 @@ bool damon_is_running(struct damon_ctx *
+ }
+
+ /**
++ * damon_kdamond_pid() - Return pid of a given DAMON context's worker thread.
++ * @ctx: The DAMON context of the question.
++ *
++ * Return: pid if @ctx is running, negative error code otherwise.
++ */
++int damon_kdamond_pid(struct damon_ctx *ctx)
++{
++ int pid = -EINVAL;
++
++ mutex_lock(&ctx->kdamond_lock);
++ if (ctx->kdamond)
++ pid = ctx->kdamond->pid;
++ mutex_unlock(&ctx->kdamond_lock);
++ return pid;
++}
++
++/**
+ * damon_call() - Invoke a given function on DAMON worker thread (kdamond).
+ * @ctx: DAMON context to call the function for.
+ * @control: Control variable of the call request.
--- /dev/null
+From b98b7ff6025ae82570d4915e083f0cbd8d48b3cf Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Sun, 19 Apr 2026 09:10:01 -0700
+Subject: mm/damon/lru_sort: detect and use fresh enabled and kdamond_pid values
+
+From: SeongJae Park <sj@kernel.org>
+
+commit b98b7ff6025ae82570d4915e083f0cbd8d48b3cf upstream.
+
+DAMON_LRU_SORT updates 'enabled' and 'kdamond_pid' parameter values, which
+represents the running status of its kdamond, when the user explicitly
+requests start/stop of the kdamond. The kdamond can, however, be stopped
+in events other than the explicit user request in the following three
+events.
+
+1. ctx->regions_score_histogram allocation failure at beginning of the
+ execution,
+2. damon_commit_ctx() failure due to invalid user input, and
+3. damon_commit_ctx() failure due to its internal allocation failures.
+
+Hence, if the kdamond is stopped by the above three events, the values of
+the status parameters can be stale. Users could show the stale values and
+be confused. This is already bad, but the real consequence is worse.
+DAMON_LRU_SORT avoids unnecessary damon_start() and damon_stop() calls
+based on the 'enabled' parameter value. And the update of 'enabled'
+parameter value depends on the damon_start() and damon_stop() call
+results. Hence, once the kdamond has stopped by the unintentional events,
+the user cannot restart the kdamond before the system reboot. For
+example, the issue can be reproduced via below steps.
+
+ # cd /sys/module/damon_lru_sort/parameters
+ #
+ # # start DAMON_LRU_SORT
+ # echo Y > enabled
+ # ps -ef | grep kdamond
+ root 806 2 0 17:53 ? 00:00:00 [kdamond.0]
+ root 808 803 0 17:53 pts/4 00:00:00 grep kdamond
+ #
+ # # commit wrong input to stop kdamond withou explicit stop request
+ # echo 3 > addr_unit
+ # echo Y > commit_inputs
+ bash: echo: write error: Invalid argument
+ #
+ # # confirm kdamond is stopped
+ # ps -ef | grep kdamond
+ root 811 803 0 17:53 pts/4 00:00:00 grep kdamond
+ #
+ # # users casn now show stable status
+ # cat enabled
+ Y
+ # cat kdamond_pid
+ 806
+ #
+ # # even after fixing the wrong parameter,
+ # # kdamond cannot be restarted.
+ # echo 1 > addr_unit
+ # echo Y > enabled
+ # ps -ef | grep kdamond
+ root 815 803 0 17:54 pts/4 00:00:00 grep kdamond
+
+The problem will only rarely happen in real and common setups for the
+following reasons. The allocation failures are unlikely in such setups
+since those allocations are arguably too small to fail. Also sane users
+on real production environments may not commit wrong input parameters.
+But once it happens, the consequence is quite bad. And the bug is a bug.
+
+The issue stems from the fact that there are multiple events that can
+change the status, and following all the events is challenging.
+Dynamically detect and use the fresh status for the parameters when those
+are requested.
+
+Link: https://lore.kernel.org/20260419161003.79176-3-sj@kernel.org
+Fixes: 40e983cca927 ("mm/damon: introduce DAMON-based LRU-lists Sorting")
+Co-developed-by: Liew Rui Yan <aethernet65535@gmail.com>
+Signed-off-by: Liew Rui Yan <aethernet65535@gmail.com>
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 6.0.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/lru_sort.c | 83 ++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 55 insertions(+), 28 deletions(-)
+
+--- a/mm/damon/lru_sort.c
++++ b/mm/damon/lru_sort.c
+@@ -118,15 +118,6 @@ module_param(monitor_region_end, ulong,
+ */
+ static unsigned long addr_unit __read_mostly = 1;
+
+-/*
+- * PID of the DAMON thread
+- *
+- * If DAMON_LRU_SORT is enabled, this becomes the PID of the worker thread.
+- * Else, -1.
+- */
+-static int kdamond_pid __read_mostly = -1;
+-module_param(kdamond_pid, int, 0400);
+-
+ static struct damos_stat damon_lru_sort_hot_stat;
+ DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_lru_sort_hot_stat,
+ lru_sort_tried_hot_regions, lru_sorted_hot_regions,
+@@ -288,12 +279,8 @@ static int damon_lru_sort_turn(bool on)
+ {
+ int err;
+
+- if (!on) {
+- err = damon_stop(&ctx, 1);
+- if (!err)
+- kdamond_pid = -1;
+- return err;
+- }
++ if (!on)
++ return damon_stop(&ctx, 1);
+
+ err = damon_lru_sort_apply_parameters();
+ if (err)
+@@ -302,7 +289,6 @@ static int damon_lru_sort_turn(bool on)
+ err = damon_start(&ctx, 1, true);
+ if (err)
+ return err;
+- kdamond_pid = ctx->kdamond->pid;
+ return damon_call(ctx, &call_control);
+ }
+
+@@ -330,42 +316,83 @@ module_param_cb(addr_unit, &addr_unit_pa
+ MODULE_PARM_DESC(addr_unit,
+ "Scale factor for DAMON_LRU_SORT to ops address conversion (default: 1)");
+
++static bool damon_lru_sort_enabled(void)
++{
++ if (!ctx)
++ return false;
++ return damon_is_running(ctx);
++}
++
+ static int damon_lru_sort_enabled_store(const char *val,
+ const struct kernel_param *kp)
+ {
+- bool is_enabled = enabled;
+- bool enable;
+ int err;
+
+- err = kstrtobool(val, &enable);
++ err = kstrtobool(val, &enabled);
+ if (err)
+ return err;
+
+- if (is_enabled == enable)
++ if (damon_lru_sort_enabled() == enabled)
+ return 0;
+
+ /* Called before init function. The function will handle this. */
+ if (!damon_initialized())
+- goto set_param_out;
++ return 0;
+
+- err = damon_lru_sort_turn(enable);
+- if (err)
+- return err;
++ return damon_lru_sort_turn(enabled);
++}
+
+-set_param_out:
+- enabled = enable;
+- return err;
++static int damon_lru_sort_enabled_load(char *buffer,
++ const struct kernel_param *kp)
++{
++ return sprintf(buffer, "%c\n", damon_lru_sort_enabled() ? 'Y' : 'N');
+ }
+
+ static const struct kernel_param_ops enabled_param_ops = {
+ .set = damon_lru_sort_enabled_store,
+- .get = param_get_bool,
++ .get = damon_lru_sort_enabled_load,
+ };
+
+ module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
+ MODULE_PARM_DESC(enabled,
+ "Enable or disable DAMON_LRU_SORT (default: disabled)");
+
++static int damon_lru_sort_kdamond_pid_store(const char *val,
++ const struct kernel_param *kp)
++{
++ /*
++ * kdamond_pid is read-only, but kernel command line could write it.
++ * Do nothing here.
++ */
++ return 0;
++}
++
++static int damon_lru_sort_kdamond_pid_load(char *buffer,
++ const struct kernel_param *kp)
++{
++ int kdamond_pid = -1;
++
++ if (ctx) {
++ kdamond_pid = damon_kdamond_pid(ctx);
++ if (kdamond_pid < 0)
++ kdamond_pid = -1;
++ }
++ return sprintf(buffer, "%d\n", kdamond_pid);
++}
++
++static const struct kernel_param_ops kdamond_pid_param_ops = {
++ .set = damon_lru_sort_kdamond_pid_store,
++ .get = damon_lru_sort_kdamond_pid_load,
++};
++
++/*
++ * PID of the DAMON thread
++ *
++ * If DAMON_LRU_SORT is enabled, this becomes the PID of the worker thread.
++ * Else, -1.
++ */
++module_param_cb(kdamond_pid, &kdamond_pid_param_ops, NULL, 0400);
++
+ static int __init damon_lru_sort_init(void)
+ {
+ int err;
--- /dev/null
+From 64a140afa5ed1c6f5ba6d451512cbdbbab1ba339 Mon Sep 17 00:00:00 2001
+From: SeongJae Park <sj@kernel.org>
+Date: Sun, 19 Apr 2026 09:10:00 -0700
+Subject: mm/damon/reclaim: detect and use fresh enabled and kdamond_pid values
+
+From: SeongJae Park <sj@kernel.org>
+
+commit 64a140afa5ed1c6f5ba6d451512cbdbbab1ba339 upstream.
+
+Patch series "mm/damon/modules: detect and use fresh status", v3.
+
+DAMON modules including DAMON_RECLAIM, DAMON_LRU_SORT and DAMON_STAT
+commonly expose the kdamond running status via their parameters. Under
+certain scenarios including wrong user inputs and memory allocation
+failures, those parameter values can be stale. It can confuse users. For
+DAMON_RECLAIM and DAMON_LRU_SORT, it even makes the kdamond unable to be
+restarted before the system reboot.
+
+The problem comes from the fact that there are multiple events for the
+status changes and it is difficult to follow up all the scenarios. Fix
+the issue by detecting and using the status on demand, instead of using a
+cached status that is difficult to be updated.
+
+Patches 1-3 fix the bugs in DAMON_RECLAIM, DAMON_LRU_SORT and DAMON_STAT
+in the order.
+
+
+This patch (of 3):
+
+DAMON_RECLAIM updates 'enabled' and 'kdamond_pid' parameter values, which
+represents the running status of its kdamond, when the user explicitly
+requests start/stop of the kdamond. The kdamond can, however, be stopped
+in events other than the explicit user request in the following three
+events.
+
+1. ctx->regions_score_histogram allocation failure at beginning of the
+ execution,
+2. damon_commit_ctx() failure due to invalid user input, and
+3. damon_commit_ctx() failure due to its internal allocation failures.
+
+Hence, if the kdamond is stopped by the above three events, the values of
+the status parameters can be stale. Users could show the stale values and
+be confused. This is already bad, but the real consequence is worse.
+DAMON_RECLAIM avoids unnecessary damon_start() and damon_stop() calls
+based on the 'enabled' parameter value. And the update of 'enabled'
+parameter value depends on the damon_start() and damon_stop() call
+results. Hence, once the kdamond has stopped by the unintentional events,
+the user cannot restart the kdamond before the system reboot. For
+example, the issue can be reproduced via below steps.
+
+ # cd /sys/module/damon_reclaim/parameters
+ #
+ # # start DAMON_RECLAIM
+ # echo Y > enabled
+ # ps -ef | grep kdamond
+ root 806 2 0 17:53 ? 00:00:00 [kdamond.0]
+ root 808 803 0 17:53 pts/4 00:00:00 grep kdamond
+ #
+ # # commit wrong input to stop kdamond withou explicit stop request
+ # echo 3 > addr_unit
+ # echo Y > commit_inputs
+ bash: echo: write error: Invalid argument
+ #
+ # # confirm kdamond is stopped
+ # ps -ef | grep kdamond
+ root 811 803 0 17:53 pts/4 00:00:00 grep kdamond
+ #
+ # # users casn now show stable status
+ # cat enabled
+ Y
+ # cat kdamond_pid
+ 806
+ #
+ # # even after fixing the wrong parameter,
+ # # kdamond cannot be restarted.
+ # echo 1 > addr_unit
+ # echo Y > enabled
+ # ps -ef | grep kdamond
+ root 815 803 0 17:54 pts/4 00:00:00 grep kdamond
+
+The problem will only rarely happen in real and common setups for the
+following reasons. The allocation failures are unlikely in such setups
+since those allocations are arguably too small to fail. Also sane users
+on real production environments may not commit wrong input parameters.
+But once it happens, the consequence is quite bad. And the bug is a bug.
+
+The issue stems from the fact that there are multiple events that can
+change the status, and following all the events is challenging.
+Dynamically detect and use the fresh status for the parameters when those
+are requested.
+
+Link: https://lore.kernel.org/20260419161003.79176-1-sj@kernel.org
+Link: https://lore.kernel.org/20260419161003.79176-2-sj@kernel.org
+Fixes: e035c280f6df ("mm/damon/reclaim: support online inputs update")
+Co-developed-by: Liew Rui Yan <aethernet65535@gmail.com>
+Signed-off-by: Liew Rui Yan <aethernet65535@gmail.com>
+Signed-off-by: SeongJae Park <sj@kernel.org>
+Cc: <stable@vger.kernel.org> # 5.19.x
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ mm/damon/reclaim.c | 83 +++++++++++++++++++++++++++++++++++------------------
+ 1 file changed, 55 insertions(+), 28 deletions(-)
+
+--- a/mm/damon/reclaim.c
++++ b/mm/damon/reclaim.c
+@@ -144,15 +144,6 @@ static unsigned long addr_unit __read_mo
+ static bool skip_anon __read_mostly;
+ module_param(skip_anon, bool, 0600);
+
+-/*
+- * PID of the DAMON thread
+- *
+- * If DAMON_RECLAIM is enabled, this becomes the PID of the worker thread.
+- * Else, -1.
+- */
+-static int kdamond_pid __read_mostly = -1;
+-module_param(kdamond_pid, int, 0400);
+-
+ static struct damos_stat damon_reclaim_stat;
+ DEFINE_DAMON_MODULES_DAMOS_STATS_PARAMS(damon_reclaim_stat,
+ reclaim_tried_regions, reclaimed_regions, quota_exceeds);
+@@ -292,12 +283,8 @@ static int damon_reclaim_turn(bool on)
+ {
+ int err;
+
+- if (!on) {
+- err = damon_stop(&ctx, 1);
+- if (!err)
+- kdamond_pid = -1;
+- return err;
+- }
++ if (!on)
++ return damon_stop(&ctx, 1);
+
+ err = damon_reclaim_apply_parameters();
+ if (err)
+@@ -306,7 +293,6 @@ static int damon_reclaim_turn(bool on)
+ err = damon_start(&ctx, 1, true);
+ if (err)
+ return err;
+- kdamond_pid = ctx->kdamond->pid;
+ return damon_call(ctx, &call_control);
+ }
+
+@@ -334,42 +320,83 @@ module_param_cb(addr_unit, &addr_unit_pa
+ MODULE_PARM_DESC(addr_unit,
+ "Scale factor for DAMON_RECLAIM to ops address conversion (default: 1)");
+
++static bool damon_reclaim_enabled(void)
++{
++ if (!ctx)
++ return false;
++ return damon_is_running(ctx);
++}
++
+ static int damon_reclaim_enabled_store(const char *val,
+ const struct kernel_param *kp)
+ {
+- bool is_enabled = enabled;
+- bool enable;
+ int err;
+
+- err = kstrtobool(val, &enable);
++ err = kstrtobool(val, &enabled);
+ if (err)
+ return err;
+
+- if (is_enabled == enable)
++ if (damon_reclaim_enabled() == enabled)
+ return 0;
+
+ /* Called before init function. The function will handle this. */
+ if (!damon_initialized())
+- goto set_param_out;
++ return 0;
+
+- err = damon_reclaim_turn(enable);
+- if (err)
+- return err;
++ return damon_reclaim_turn(enabled);
++}
+
+-set_param_out:
+- enabled = enable;
+- return err;
++static int damon_reclaim_enabled_load(char *buffer,
++ const struct kernel_param *kp)
++{
++ return sprintf(buffer, "%c\n", damon_reclaim_enabled() ? 'Y' : 'N');
+ }
+
+ static const struct kernel_param_ops enabled_param_ops = {
+ .set = damon_reclaim_enabled_store,
+- .get = param_get_bool,
++ .get = damon_reclaim_enabled_load,
+ };
+
+ module_param_cb(enabled, &enabled_param_ops, &enabled, 0600);
+ MODULE_PARM_DESC(enabled,
+ "Enable or disable DAMON_RECLAIM (default: disabled)");
+
++static int damon_reclaim_kdamond_pid_store(const char *val,
++ const struct kernel_param *kp)
++{
++ /*
++ * kdamond_pid is read-only, but kernel command line could write it.
++ * Do nothing here.
++ */
++ return 0;
++}
++
++static int damon_reclaim_kdamond_pid_load(char *buffer,
++ const struct kernel_param *kp)
++{
++ int kdamond_pid = -1;
++
++ if (ctx) {
++ kdamond_pid = damon_kdamond_pid(ctx);
++ if (kdamond_pid < 0)
++ kdamond_pid = -1;
++ }
++ return sprintf(buffer, "%d\n", kdamond_pid);
++}
++
++static const struct kernel_param_ops kdamond_pid_param_ops = {
++ .set = damon_reclaim_kdamond_pid_store,
++ .get = damon_reclaim_kdamond_pid_load,
++};
++
++/*
++ * PID of the DAMON thread
++ *
++ * If DAMON_RECLAIM is enabled, this becomes the PID of the worker thread.
++ * Else, -1.
++ */
++module_param_cb(kdamond_pid, &kdamond_pid_param_ops, NULL, 0400);
++
+ static int __init damon_reclaim_init(void)
+ {
+ int err;
--- /dev/null
+From stable+bounces-247227-greg=kroah.com@vger.kernel.org Thu May 14 17:10:50 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 11:08:19 -0400
+Subject: papr-hvpipe: convert papr_hvpipe_dev_create_handle() to FD_PREPARE()
+To: stable@vger.kernel.org
+Cc: Christian Brauner <brauner@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514150820.274333-1-sashal@kernel.org>
+
+From: Christian Brauner <brauner@kernel.org>
+
+[ Upstream commit 6d3789d347a7af5c4b0b2da3af47b8d9da607ab2 ]
+
+Fixes a UAF for src_info as well.
+
+Link: https://patch.msgid.link/20251123-work-fd-prepare-v4-33-b6efa1706cfd@kernel.org
+Signed-off-by: Christian Brauner <brauner@kernel.org>
+Stable-dep-of: 7a4f0846ee6c ("pseries/papr-hvpipe: Fix race with interrupt handler")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/platforms/pseries/papr-hvpipe.c | 39 ++++++---------------------
+ 1 file changed, 9 insertions(+), 30 deletions(-)
+
+--- a/arch/powerpc/platforms/pseries/papr-hvpipe.c
++++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c
+@@ -484,10 +484,7 @@ static const struct file_operations papr
+
+ static int papr_hvpipe_dev_create_handle(u32 srcID)
+ {
+- struct hvpipe_source_info *src_info;
+- struct file *file;
+- long err;
+- int fd;
++ struct hvpipe_source_info *src_info __free(kfree) = NULL;
+
+ spin_lock(&hvpipe_src_list_lock);
+ /*
+@@ -511,20 +508,13 @@ static int papr_hvpipe_dev_create_handle
+ src_info->tsk = current;
+ init_waitqueue_head(&src_info->recv_wqh);
+
+- fd = get_unused_fd_flags(O_RDONLY | O_CLOEXEC);
+- if (fd < 0) {
+- err = fd;
+- goto free_buf;
+- }
+-
+- file = anon_inode_getfile("[papr-hvpipe]",
+- &papr_hvpipe_handle_ops, (void *)src_info,
+- O_RDWR);
+- if (IS_ERR(file)) {
+- err = PTR_ERR(file);
+- goto free_fd;
+- }
++ FD_PREPARE(fdf, O_RDONLY | O_CLOEXEC,
++ anon_inode_getfile("[papr-hvpipe]", &papr_hvpipe_handle_ops,
++ (void *)src_info, O_RDWR));
++ if (fdf.err)
++ return fdf.err;
+
++ retain_and_null_ptr(src_info);
+ spin_lock(&hvpipe_src_list_lock);
+ /*
+ * If two processes are executing ioctl() for the same
+@@ -533,22 +523,11 @@ static int papr_hvpipe_dev_create_handle
+ */
+ if (hvpipe_find_source(srcID)) {
+ spin_unlock(&hvpipe_src_list_lock);
+- err = -EALREADY;
+- goto free_file;
++ return -EALREADY;
+ }
+ list_add(&src_info->list, &hvpipe_src_list);
+ spin_unlock(&hvpipe_src_list_lock);
+-
+- fd_install(fd, file);
+- return fd;
+-
+-free_file:
+- fput(file);
+-free_fd:
+- put_unused_fd(fd);
+-free_buf:
+- kfree(src_info);
+- return err;
++ return fd_publish(fdf);
+ }
+
+ /*
--- /dev/null
+From stable+bounces-247228-greg=kroah.com@vger.kernel.org Thu May 14 17:16:59 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 11:08:20 -0400
+Subject: pseries/papr-hvpipe: Fix race with interrupt handler
+To: stable@vger.kernel.org
+Cc: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>, Madhavan Srinivasan <maddy@linux.ibm.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514150820.274333-2-sashal@kernel.org>
+
+From: "Ritesh Harjani (IBM)" <ritesh.list@gmail.com>
+
+[ Upstream commit 7a4f0846ee6cc8cf44ae0046ed42e3259d1dd45b ]
+
+While executing ->ioctl handler or ->release handler, if an interrupt
+fires on the same cpu, then we can enter into a deadlock.
+
+This patch fixes both these handlers to take spin_lock_irq{save|restore}
+versions of the lock to prevent this deadlock.
+
+Cc: stable@vger.kernel.org
+Fixes: 814ef095f12c9 ("powerpc/pseries: Add papr-hvpipe char driver for HVPIPE interfaces")
+Signed-off-by: Ritesh Harjani (IBM) <ritesh.list@gmail.com>
+Signed-off-by: Madhavan Srinivasan <maddy@linux.ibm.com>
+Link: https://patch.msgid.link/e4ed435c44fc191f2eb23c7907ba6f72f193e6aa.1777606826.git.ritesh.list@gmail.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ arch/powerpc/platforms/pseries/papr-hvpipe.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+--- a/arch/powerpc/platforms/pseries/papr-hvpipe.c
++++ b/arch/powerpc/platforms/pseries/papr-hvpipe.c
+@@ -449,13 +449,14 @@ static int papr_hvpipe_handle_release(st
+ struct file *file)
+ {
+ struct hvpipe_source_info *src_info;
++ unsigned long flags;
+
+ /*
+ * Hold the lock, remove source from src_list, reset the
+ * hvpipe status and release the lock to prevent any race
+ * with message event IRQ.
+ */
+- spin_lock(&hvpipe_src_list_lock);
++ spin_lock_irqsave(&hvpipe_src_list_lock, flags);
+ src_info = file->private_data;
+ list_del(&src_info->list);
+ file->private_data = NULL;
+@@ -466,10 +467,10 @@ static int papr_hvpipe_handle_release(st
+ */
+ if (src_info->hvpipe_status & HVPIPE_MSG_AVAILABLE) {
+ src_info->hvpipe_status = 0;
+- spin_unlock(&hvpipe_src_list_lock);
++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
+ hvpipe_rtas_recv_msg(NULL, 0);
+ } else
+- spin_unlock(&hvpipe_src_list_lock);
++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
+
+ kfree(src_info);
+ return 0;
+@@ -485,20 +486,21 @@ static const struct file_operations papr
+ static int papr_hvpipe_dev_create_handle(u32 srcID)
+ {
+ struct hvpipe_source_info *src_info __free(kfree) = NULL;
++ unsigned long flags;
+
+- spin_lock(&hvpipe_src_list_lock);
++ spin_lock_irqsave(&hvpipe_src_list_lock, flags);
+ /*
+ * Do not allow more than one process communicates with
+ * each source.
+ */
+ src_info = hvpipe_find_source(srcID);
+ if (src_info) {
+- spin_unlock(&hvpipe_src_list_lock);
++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
+ pr_err("pid(%d) is already using the source(%d)\n",
+ src_info->tsk->pid, srcID);
+ return -EALREADY;
+ }
+- spin_unlock(&hvpipe_src_list_lock);
++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
+
+ src_info = kzalloc(sizeof(*src_info), GFP_KERNEL_ACCOUNT);
+ if (!src_info)
+@@ -515,18 +517,18 @@ static int papr_hvpipe_dev_create_handle
+ return fdf.err;
+
+ retain_and_null_ptr(src_info);
+- spin_lock(&hvpipe_src_list_lock);
++ spin_lock_irqsave(&hvpipe_src_list_lock, flags);
+ /*
+ * If two processes are executing ioctl() for the same
+ * source ID concurrently, prevent the second process to
+ * acquire FD.
+ */
+ if (hvpipe_find_source(srcID)) {
+- spin_unlock(&hvpipe_src_list_lock);
++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
+ return -EALREADY;
+ }
+ list_add(&src_info->list, &hvpipe_src_list);
+- spin_unlock(&hvpipe_src_list_lock);
++ spin_unlock_irqrestore(&hvpipe_src_list_lock, flags);
+ return fd_publish(fdf);
+ }
+
--- /dev/null
+From 9163fe4d790fb4e16d6b0e23f55b43cddd3d4a65 Mon Sep 17 00:00:00 2001
+From: Prike Liang <Prike.Liang@amd.com>
+Date: Fri, 9 Jan 2026 16:15:11 +0800
+Subject: Revert "drm/amdgpu: don't attach the tlb fence for SI"
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Prike Liang <Prike.Liang@amd.com>
+
+commit 9163fe4d790fb4e16d6b0e23f55b43cddd3d4a65 upstream.
+
+This reverts commit 820b3d376e8a102c6aeab737ec6edebbbb710e04.
+
+It’s better to validate VM TLB flushes in the flush‑TLB backend
+rather than in the generic VM layer.
+
+Reverting this patch depends on
+commit fa7c231fc2b0 ("drm/amdgpu: validate the flush_gpu_tlb_pasid()")
+being present in the tree.
+
+Signed-off-by: Prike Liang <Prike.Liang@amd.com>
+Reviewed-by: Christian König <christian.koenig@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -1066,9 +1066,7 @@ amdgpu_vm_tlb_flush(struct amdgpu_vm_upd
+ }
+
+ /* Prepare a TLB flush fence to be attached to PTs */
+- if (!params->unlocked &&
+- /* SI doesn't support pasid or KIQ/MES */
+- params->adev->family > AMDGPU_FAMILY_SI) {
++ if (!params->unlocked) {
+ amdgpu_vm_tlb_fence_create(params->adev, vm, fence);
+
+ /* Makes sure no PD/PT is freed before the flush */
--- /dev/null
+From stable+bounces-246937-greg=kroah.com@vger.kernel.org Wed May 13 19:04:56 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 12:33:21 -0400
+Subject: sched/ext: Implement cgroup_set_idle() callback
+To: stable@vger.kernel.org
+Cc: zhidao su <suzhidao@xiaomi.com>, zhidao su <soolaugust@gmail.com>, Tejun Heo <tj@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513163322.3807202-1-sashal@kernel.org>
+
+From: zhidao su <suzhidao@xiaomi.com>
+
+[ Upstream commit 347ed2d566dabb06c7970fff01129c4f59995ed6 ]
+
+Implement the missing cgroup_set_idle() callback that was marked as a
+TODO. This allows BPF schedulers to be notified when a cgroup's idle
+state changes, enabling them to adjust their scheduling behavior
+accordingly.
+
+The implementation follows the same pattern as other cgroup callbacks
+like cgroup_set_weight() and cgroup_set_bandwidth(). It checks if the
+BPF scheduler has implemented the callback and invokes it with the
+appropriate parameters.
+
+Fixes a spelling error in the cgroup_set_bandwidth() documentation.
+
+tj: s/scx_cgroup_rwsem/scx_cgroup_ops_rwsem/ to fix build breakage.
+
+Signed-off-by: zhidao su <soolaugust@gmail.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Stable-dep-of: 80afd4c84bc8 ("sched_ext: Read scx_root under scx_cgroup_ops_rwsem in cgroup setters")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/linux/sched/ext.h | 1 +
+ kernel/sched/ext.c | 16 +++++++++++++++-
+ kernel/sched/ext_internal.h | 13 ++++++++++++-
+ 3 files changed, 28 insertions(+), 2 deletions(-)
+
+--- a/include/linux/sched/ext.h
++++ b/include/linux/sched/ext.h
+@@ -228,6 +228,7 @@ struct scx_task_group {
+ u64 bw_period_us;
+ u64 bw_quota_us;
+ u64 bw_burst_us;
++ bool idle;
+ #endif
+ };
+
+--- a/kernel/sched/ext.c
++++ b/kernel/sched/ext.c
+@@ -3118,6 +3118,7 @@ void scx_tg_init(struct task_group *tg)
+ tg->scx.weight = CGROUP_WEIGHT_DFL;
+ tg->scx.bw_period_us = default_bw_period_us();
+ tg->scx.bw_quota_us = RUNTIME_INF;
++ tg->scx.idle = false;
+ }
+
+ int scx_tg_online(struct task_group *tg)
+@@ -3266,7 +3267,18 @@ void scx_group_set_weight(struct task_gr
+
+ void scx_group_set_idle(struct task_group *tg, bool idle)
+ {
+- /* TODO: Implement ops->cgroup_set_idle() */
++ struct scx_sched *sch = scx_root;
++
++ percpu_down_read(&scx_cgroup_ops_rwsem);
++
++ if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_idle))
++ SCX_CALL_OP(sch, SCX_KF_UNLOCKED, cgroup_set_idle, NULL,
++ tg_cgrp(tg), idle);
++
++ /* Update the task group's idle state */
++ tg->scx.idle = idle;
++
++ percpu_up_read(&scx_cgroup_ops_rwsem);
+ }
+
+ void scx_group_set_bandwidth(struct task_group *tg,
+@@ -5125,6 +5137,7 @@ static void sched_ext_ops__cgroup_move(s
+ static void sched_ext_ops__cgroup_cancel_move(struct task_struct *p, struct cgroup *from, struct cgroup *to) {}
+ static void sched_ext_ops__cgroup_set_weight(struct cgroup *cgrp, u32 weight) {}
+ static void sched_ext_ops__cgroup_set_bandwidth(struct cgroup *cgrp, u64 period_us, u64 quota_us, u64 burst_us) {}
++static void sched_ext_ops__cgroup_set_idle(struct cgroup *cgrp, bool idle) {}
+ #endif
+ static void sched_ext_ops__cpu_online(s32 cpu) {}
+ static void sched_ext_ops__cpu_offline(s32 cpu) {}
+@@ -5163,6 +5176,7 @@ static struct sched_ext_ops __bpf_ops_sc
+ .cgroup_cancel_move = sched_ext_ops__cgroup_cancel_move,
+ .cgroup_set_weight = sched_ext_ops__cgroup_set_weight,
+ .cgroup_set_bandwidth = sched_ext_ops__cgroup_set_bandwidth,
++ .cgroup_set_idle = sched_ext_ops__cgroup_set_idle,
+ #endif
+ .cpu_online = sched_ext_ops__cpu_online,
+ .cpu_offline = sched_ext_ops__cpu_offline,
+--- a/kernel/sched/ext_internal.h
++++ b/kernel/sched/ext_internal.h
+@@ -697,12 +697,23 @@ struct sched_ext_ops {
+ * 2_500_000. @cgrp is entitled to 2.5 CPUs. @burst_us can be
+ * interpreted in the same fashion and specifies how much @cgrp can
+ * burst temporarily. The specific control mechanism and thus the
+- * interpretation of @period_us and burstiness is upto to the BPF
++ * interpretation of @period_us and burstiness is up to the BPF
+ * scheduler.
+ */
+ void (*cgroup_set_bandwidth)(struct cgroup *cgrp,
+ u64 period_us, u64 quota_us, u64 burst_us);
+
++ /**
++ * @cgroup_set_idle: A cgroup's idle state is being changed
++ * @cgrp: cgroup whose idle state is being updated
++ * @idle: whether the cgroup is entering or exiting idle state
++ *
++ * Update @cgrp's idle state to @idle. This callback is invoked when
++ * a cgroup transitions between idle and non-idle states, allowing the
++ * BPF scheduler to adjust its behavior accordingly.
++ */
++ void (*cgroup_set_idle)(struct cgroup *cgrp, bool idle);
++
+ #endif /* CONFIG_EXT_GROUP_SCHED */
+
+ /*
--- /dev/null
+From stable+bounces-246938-greg=kroah.com@vger.kernel.org Wed May 13 18:42:02 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 12:33:22 -0400
+Subject: sched_ext: Read scx_root under scx_cgroup_ops_rwsem in cgroup setters
+To: stable@vger.kernel.org
+Cc: Tejun Heo <tj@kernel.org>, Chris Mason <clm@meta.com>, Andrea Righi <arighi@nvidia.com>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513163322.3807202-2-sashal@kernel.org>
+
+From: Tejun Heo <tj@kernel.org>
+
+[ Upstream commit 80afd4c84bc8f5e80145ce35279f5ce53f6043db ]
+
+scx_group_set_{weight,idle,bandwidth}() cache scx_root before acquiring
+scx_cgroup_ops_rwsem, so the pointer can be stale by the time the op runs.
+If the loaded scheduler is disabled and freed (via RCU work) and another is
+enabled between the naked load and the rwsem acquire, the reader sees
+scx_cgroup_enabled=true (the new scheduler's) but dereferences the freed one
+- UAF on SCX_HAS_OP(sch, ...) / SCX_CALL_OP(sch, ...).
+
+scx_cgroup_enabled is toggled only under scx_cgroup_ops_rwsem write
+(scx_cgroup_{init,exit}), so reading scx_root inside the rwsem read section
+correlates @sch with the enabled snapshot.
+
+Fixes: a5bd6ba30b33 ("sched_ext: Use cgroup_lock/unlock() to synchronize against cgroup operations")
+Cc: stable@vger.kernel.org # v6.18+
+Reported-by: Chris Mason <clm@meta.com>
+Signed-off-by: Tejun Heo <tj@kernel.org>
+Reviewed-by: Andrea Righi <arighi@nvidia.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ kernel/sched/ext.c | 9 ++++++---
+ 1 file changed, 6 insertions(+), 3 deletions(-)
+
+--- a/kernel/sched/ext.c
++++ b/kernel/sched/ext.c
+@@ -3251,9 +3251,10 @@ void scx_cgroup_cancel_attach(struct cgr
+
+ void scx_group_set_weight(struct task_group *tg, unsigned long weight)
+ {
+- struct scx_sched *sch = scx_root;
++ struct scx_sched *sch;
+
+ percpu_down_read(&scx_cgroup_ops_rwsem);
++ sch = scx_root;
+
+ if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_weight) &&
+ tg->scx.weight != weight)
+@@ -3267,9 +3268,10 @@ void scx_group_set_weight(struct task_gr
+
+ void scx_group_set_idle(struct task_group *tg, bool idle)
+ {
+- struct scx_sched *sch = scx_root;
++ struct scx_sched *sch;
+
+ percpu_down_read(&scx_cgroup_ops_rwsem);
++ sch = scx_root;
+
+ if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_idle))
+ SCX_CALL_OP(sch, SCX_KF_UNLOCKED, cgroup_set_idle, NULL,
+@@ -3284,9 +3286,10 @@ void scx_group_set_idle(struct task_grou
+ void scx_group_set_bandwidth(struct task_group *tg,
+ u64 period_us, u64 quota_us, u64 burst_us)
+ {
+- struct scx_sched *sch = scx_root;
++ struct scx_sched *sch;
+
+ percpu_down_read(&scx_cgroup_ops_rwsem);
++ sch = scx_root;
+
+ if (scx_cgroup_enabled && SCX_HAS_OP(sch, cgroup_set_bandwidth) &&
+ (tg->scx.bw_period_us != period_us ||
sched_ext-use-hk_type_domain_boot-to-detect-isolcpus-domain-isolation.patch
io_uring-zcrx-use-guards-for-locking.patch
io_uring-zcrx-warn-on-freelist-violations.patch
+loongarch-kvm-compile-switch.s-directly-into-the-kernel.patch
+mm-damon-core-implement-damon_kdamond_pid.patch
+mm-damon-lru_sort-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch
+mm-damon-reclaim-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch
+usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch
+mm-damon-core-disallow-time-quota-setting-zero-esz.patch
+drm-amdgpu-validate-the-flush_gpu_tlb_pasid.patch
+drm-amdgpu-fix-validating-flush_gpu_tlb_pasid.patch
+revert-drm-amdgpu-don-t-attach-the-tlb-fence-for-si.patch
+drm-amdgpu-rework-how-we-handle-tlb-fences.patch
+fbcon-rename-struct-fbcon_ops-to-struct-fbcon_par.patch
+fbcon-avoid-oob-font-access-if-console-rotation-fails.patch
+block-fix-zone-write-plug-removal.patch
+edac-versalnet-fix-device-name-memory-leak.patch
+papr-hvpipe-convert-papr_hvpipe_dev_create_handle-to-fd_prepare.patch
+pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch
+spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch
+spi-uniphier-fix-controller-deregistration.patch
+spi-tegra20-sflash-fix-controller-deregistration.patch
+spi-tegra114-fix-controller-deregistration.patch
+spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch
+spi-zynq-qspi-fix-controller-deregistration.patch
+bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch
+sched-ext-implement-cgroup_set_idle-callback.patch
+sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch
+usb-dwc3-remove-of-dep-regs.patch
+usb-dwc3-add-dwc-pointer-to-dwc3_readl-writel.patch
+usb-dwc3-move-guid-programming-after-phy-initialization.patch
--- /dev/null
+From stable+bounces-247094-greg=kroah.com@vger.kernel.org Thu May 14 05:10:44 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 23:10:37 -0400
+Subject: spi: tegra114: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Jingoo Han <jg1.han@samsung.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514031037.4119194-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 9c9c27ff2058142d8f800de3186d6864184958de ]
+
+Make sure to deregister the controller before disabling underlying
+resources like clocks during driver unbind.
+
+Fixes: 5c8096439600 ("spi: tegra114: use devm_spi_register_master()")
+Cc: stable@vger.kernel.org # 3.13
+Cc: Jingoo Han <jg1.han@samsung.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-22-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+[ kept `host->dev.of_node = pdev->dev.of_node;` context line above the `spi_register_controller()` conversion ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-tegra114.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-tegra114.c
++++ b/drivers/spi/spi-tegra114.c
+@@ -1416,7 +1416,7 @@ static int tegra_spi_probe(struct platfo
+ }
+
+ host->dev.of_node = pdev->dev.of_node;
+- ret = devm_spi_register_controller(&pdev->dev, host);
++ ret = spi_register_controller(host);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can not register to host err %d\n", ret);
+ goto exit_free_irq;
+@@ -1442,6 +1442,10 @@ static void tegra_spi_remove(struct plat
+ struct spi_controller *host = platform_get_drvdata(pdev);
+ struct tegra_spi_data *tspi = spi_controller_get_devdata(host);
+
++ spi_controller_get(host);
++
++ spi_unregister_controller(host);
++
+ free_irq(tspi->irq, tspi);
+
+ if (tspi->tx_dma_chan)
+@@ -1453,6 +1457,8 @@ static void tegra_spi_remove(struct plat
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra_spi_runtime_suspend(&pdev->dev);
++
++ spi_controller_put(host);
+ }
+
+ #ifdef CONFIG_PM_SLEEP
--- /dev/null
+From stable+bounces-247099-greg=kroah.com@vger.kernel.org Thu May 14 06:16:21 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 00:14:46 -0400
+Subject: spi: tegra20-sflash: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Jingoo Han <jg1.han@samsung.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514041446.4193882-1-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit ad7310e983327f939dd6c4e801eab13238992572 ]
+
+Make sure to deregister the controller before disabling underlying
+resources like clocks during driver unbind.
+
+Fixes: f12f7318c44a ("spi: tegra20-sflash: use devm_spi_register_master()")
+Cc: stable@vger.kernel.org # 3.13
+Cc: Jingoo Han <jg1.han@samsung.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-23-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+[ kept the redundant `host->dev.of_node = pdev->dev.of_node;` line above the registration call ]
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-tegra20-sflash.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-tegra20-sflash.c
++++ b/drivers/spi/spi-tegra20-sflash.c
+@@ -506,7 +506,7 @@ static int tegra_sflash_probe(struct pla
+ pm_runtime_put(&pdev->dev);
+
+ host->dev.of_node = pdev->dev.of_node;
+- ret = devm_spi_register_controller(&pdev->dev, host);
++ ret = spi_register_controller(host);
+ if (ret < 0) {
+ dev_err(&pdev->dev, "can not register to host err %d\n", ret);
+ goto exit_pm_disable;
+@@ -529,11 +529,17 @@ static void tegra_sflash_remove(struct p
+ struct spi_controller *host = platform_get_drvdata(pdev);
+ struct tegra_sflash_data *tsd = spi_controller_get_devdata(host);
+
++ spi_controller_get(host);
++
++ spi_unregister_controller(host);
++
+ free_irq(tsd->irq, tsd);
+
+ pm_runtime_disable(&pdev->dev);
+ if (!pm_runtime_status_suspended(&pdev->dev))
+ tegra_sflash_runtime_suspend(&pdev->dev);
++
++ spi_controller_put(host);
+ }
+
+ #ifdef CONFIG_PM_SLEEP
--- /dev/null
+From stable+bounces-247110-greg=kroah.com@vger.kernel.org Thu May 14 06:58:43 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 00:58:33 -0400
+Subject: spi: uniphier: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Keiji Hayashibara <hayashibara.keiji@socionext.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514045833.24151-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit 0245435f777264ac45945ed2f325dd095a41d1af ]
+
+Make sure to deregister the controller before releasing underlying
+resources like DMA during driver unbind.
+
+Note that clocks were also disabled before the recent commit
+fdca270f8f87 ("spi: uniphier: Simplify clock handling with
+devm_clk_get_enabled()").
+
+Fixes: 5ba155a4d4cc ("spi: add SPI controller driver for UniPhier SoC")
+Cc: stable@vger.kernel.org # 4.19
+Cc: Keiji Hayashibara <hayashibara.keiji@socionext.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-25-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-uniphier.c | 8 +++++++-
+ 1 file changed, 7 insertions(+), 1 deletion(-)
+
+--- a/drivers/spi/spi-uniphier.c
++++ b/drivers/spi/spi-uniphier.c
+@@ -747,7 +747,7 @@ static int uniphier_spi_probe(struct pla
+
+ host->max_dma_len = min(dma_tx_burst, dma_rx_burst);
+
+- ret = devm_spi_register_controller(&pdev->dev, host);
++ ret = spi_register_controller(host);
+ if (ret)
+ goto out_release_dma;
+
+@@ -772,10 +772,16 @@ static void uniphier_spi_remove(struct p
+ {
+ struct spi_controller *host = platform_get_drvdata(pdev);
+
++ spi_controller_get(host);
++
++ spi_unregister_controller(host);
++
+ if (host->dma_tx)
+ dma_release_channel(host->dma_tx);
+ if (host->dma_rx)
+ dma_release_channel(host->dma_rx);
++
++ spi_controller_put(host);
+ }
+
+ static const struct of_device_id uniphier_spi_match[] = {
--- /dev/null
+From stable+bounces-247109-greg=kroah.com@vger.kernel.org Thu May 14 06:58:44 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 14 May 2026 00:58:32 -0400
+Subject: spi: uniphier: Simplify clock handling with devm_clk_get_enabled()
+To: stable@vger.kernel.org
+Cc: Pei Xiao <xiaopei01@kylinos.cn>, Kunihiko Hayashi <hayashi.kunihiko@socionext.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260514045833.24151-1-sashal@kernel.org>
+
+From: Pei Xiao <xiaopei01@kylinos.cn>
+
+[ Upstream commit fdca270f8f87cae2eb5b619234b9dd11a863ce6b ]
+
+Replace devm_clk_get() followed by clk_prepare_enable() with
+devm_clk_get_enabled() for the clock. This removes the need for
+explicit clock enable and disable calls, as the managed API automatically
+handles clock disabling on device removal or probe failure.
+
+Remove the now-unnecessary clk_disable_unprepare() calls from the probe
+error path and the remove callback. Adjust error labels accordingly.
+
+Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn>
+Reviewed-by: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+Link: https://patch.msgid.link/b2deeefd4ef1a4bce71116aabfcb7e81400f6d37.1775546948.git.xiaopei01@kylinos.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: 0245435f7772 ("spi: uniphier: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-uniphier.c | 18 ++++--------------
+ 1 file changed, 4 insertions(+), 14 deletions(-)
+
+--- a/drivers/spi/spi-uniphier.c
++++ b/drivers/spi/spi-uniphier.c
+@@ -666,28 +666,24 @@ static int uniphier_spi_probe(struct pla
+ }
+ priv->base_dma_addr = res->start;
+
+- priv->clk = devm_clk_get(&pdev->dev, NULL);
++ priv->clk = devm_clk_get_enabled(&pdev->dev, NULL);
+ if (IS_ERR(priv->clk)) {
+ dev_err(&pdev->dev, "failed to get clock\n");
+ ret = PTR_ERR(priv->clk);
+ goto out_host_put;
+ }
+
+- ret = clk_prepare_enable(priv->clk);
+- if (ret)
+- goto out_host_put;
+-
+ irq = platform_get_irq(pdev, 0);
+ if (irq < 0) {
+ ret = irq;
+- goto out_disable_clk;
++ goto out_host_put;
+ }
+
+ ret = devm_request_irq(&pdev->dev, irq, uniphier_spi_handler,
+ 0, "uniphier-spi", priv);
+ if (ret) {
+ dev_err(&pdev->dev, "failed to request IRQ\n");
+- goto out_disable_clk;
++ goto out_host_put;
+ }
+
+ init_completion(&priv->xfer_done);
+@@ -717,7 +713,7 @@ static int uniphier_spi_probe(struct pla
+ if (IS_ERR_OR_NULL(host->dma_tx)) {
+ if (PTR_ERR(host->dma_tx) == -EPROBE_DEFER) {
+ ret = -EPROBE_DEFER;
+- goto out_disable_clk;
++ goto out_host_put;
+ }
+ host->dma_tx = NULL;
+ dma_tx_burst = INT_MAX;
+@@ -767,9 +763,6 @@ out_release_dma:
+ host->dma_tx = NULL;
+ }
+
+-out_disable_clk:
+- clk_disable_unprepare(priv->clk);
+-
+ out_host_put:
+ spi_controller_put(host);
+ return ret;
+@@ -778,14 +771,11 @@ out_host_put:
+ static void uniphier_spi_remove(struct platform_device *pdev)
+ {
+ struct spi_controller *host = platform_get_drvdata(pdev);
+- struct uniphier_spi_priv *priv = spi_controller_get_devdata(host);
+
+ if (host->dma_tx)
+ dma_release_channel(host->dma_tx);
+ if (host->dma_rx)
+ dma_release_channel(host->dma_rx);
+-
+- clk_disable_unprepare(priv->clk);
+ }
+
+ static const struct of_device_id uniphier_spi_match[] = {
--- /dev/null
+From stable+bounces-246994-greg=kroah.com@vger.kernel.org Wed May 13 20:15:39 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 14:08:36 -0400
+Subject: spi: zynq-qspi: fix controller deregistration
+To: stable@vger.kernel.org
+Cc: Johan Hovold <johan@kernel.org>, Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513180836.3912674-2-sashal@kernel.org>
+
+From: Johan Hovold <johan@kernel.org>
+
+[ Upstream commit c9c012706c9fa8ca6d129a9161caf92ab625a3fd ]
+
+Make sure to deregister the controller before disabling it during driver
+unbind.
+
+Note that clocks were also disabled before the recent commit
+1f8fd9490e31 ("spi: zynq-qspi: Simplify clock handling with
+devm_clk_get_enabled()").
+
+Fixes: 67dca5e580f1 ("spi: spi-mem: Add support for Zynq QSPI controller")
+Cc: stable@vger.kernel.org # 5.2: 8eb2fd00f65a
+Cc: stable@vger.kernel.org # 5.2
+Cc: Naga Sureshkumar Relli <naga.sureshkumar.relli@xilinx.com>
+Signed-off-by: Johan Hovold <johan@kernel.org>
+Link: https://patch.msgid.link/20260410081757.503099-27-johan@kernel.org
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-zynq-qspi.c | 15 +++++++++++----
+ 1 file changed, 11 insertions(+), 4 deletions(-)
+
+--- a/drivers/spi/spi-zynq-qspi.c
++++ b/drivers/spi/spi-zynq-qspi.c
+@@ -643,7 +643,7 @@ static int zynq_qspi_probe(struct platfo
+
+ xqspi = spi_controller_get_devdata(ctlr);
+ xqspi->dev = dev;
+- platform_set_drvdata(pdev, xqspi);
++ platform_set_drvdata(pdev, ctlr);
+ xqspi->regs = devm_platform_ioremap_resource(pdev, 0);
+ if (IS_ERR(xqspi->regs)) {
+ ret = PTR_ERR(xqspi->regs);
+@@ -702,9 +702,9 @@ static int zynq_qspi_probe(struct platfo
+ /* QSPI controller initializations */
+ zynq_qspi_init_hw(xqspi, ctlr->num_chipselect);
+
+- ret = devm_spi_register_controller(&pdev->dev, ctlr);
++ ret = spi_register_controller(ctlr);
+ if (ret) {
+- dev_err(&pdev->dev, "devm_spi_register_controller failed\n");
++ dev_err(&pdev->dev, "failed to register controller\n");
+ goto remove_ctlr;
+ }
+
+@@ -728,9 +728,16 @@ remove_ctlr:
+ */
+ static void zynq_qspi_remove(struct platform_device *pdev)
+ {
+- struct zynq_qspi *xqspi = platform_get_drvdata(pdev);
++ struct spi_controller *ctlr = platform_get_drvdata(pdev);
++ struct zynq_qspi *xqspi = spi_controller_get_devdata(ctlr);
++
++ spi_controller_get(ctlr);
++
++ spi_unregister_controller(ctlr);
+
+ zynq_qspi_write(xqspi, ZYNQ_QSPI_ENABLE_OFFSET, 0);
++
++ spi_controller_put(ctlr);
+ }
+
+ static const struct of_device_id zynq_qspi_of_match[] = {
--- /dev/null
+From stable+bounces-246993-greg=kroah.com@vger.kernel.org Wed May 13 20:15:37 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 14:08:35 -0400
+Subject: spi: zynq-qspi: Simplify clock handling with devm_clk_get_enabled()
+To: stable@vger.kernel.org
+Cc: Pei Xiao <xiaopei01@kylinos.cn>, Michal Simek <michal.simek@amd.com>, Mark Brown <broonie@kernel.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513180836.3912674-1-sashal@kernel.org>
+
+From: Pei Xiao <xiaopei01@kylinos.cn>
+
+[ Upstream commit 1f8fd9490e3184e9a2394df2e682901a1d57ce71 ]
+
+Replace devm_clk_get() followed by clk_prepare_enable() with
+devm_clk_get_enabled() for both "pclk" and "ref_clk". This removes
+the need for explicit clock enable and disable calls, as the managed
+API automatically disables the clocks on device removal or probe
+failure.
+
+Remove the now-unnecessary clk_disable_unprepare() calls from the
+probe error paths and the remove callback. Simplify error handling
+by jumping directly to the remove_ctlr label.
+
+Signed-off-by: Pei Xiao <xiaopei01@kylinos.cn>
+Acked-by: Michal Simek <michal.simek@amd.com>
+Link: https://patch.msgid.link/24043625f89376da36feca2408f990a85be7ab36.1775555500.git.xiaopei01@kylinos.cn
+Signed-off-by: Mark Brown <broonie@kernel.org>
+Stable-dep-of: c9c012706c9f ("spi: zynq-qspi: fix controller deregistration")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/spi/spi-zynq-qspi.c | 42 ++++++------------------------------------
+ 1 file changed, 6 insertions(+), 36 deletions(-)
+
+--- a/drivers/spi/spi-zynq-qspi.c
++++ b/drivers/spi/spi-zynq-qspi.c
+@@ -381,21 +381,10 @@ static int zynq_qspi_setup_op(struct spi
+ {
+ struct spi_controller *ctlr = spi->controller;
+ struct zynq_qspi *qspi = spi_controller_get_devdata(ctlr);
+- int ret;
+
+ if (ctlr->busy)
+ return -EBUSY;
+
+- ret = clk_enable(qspi->refclk);
+- if (ret)
+- return ret;
+-
+- ret = clk_enable(qspi->pclk);
+- if (ret) {
+- clk_disable(qspi->refclk);
+- return ret;
+- }
+-
+ zynq_qspi_write(qspi, ZYNQ_QSPI_ENABLE_OFFSET,
+ ZYNQ_QSPI_ENABLE_ENABLE_MASK);
+
+@@ -661,7 +650,7 @@ static int zynq_qspi_probe(struct platfo
+ goto remove_ctlr;
+ }
+
+- xqspi->pclk = devm_clk_get(&pdev->dev, "pclk");
++ xqspi->pclk = devm_clk_get_enabled(&pdev->dev, "pclk");
+ if (IS_ERR(xqspi->pclk)) {
+ dev_err(&pdev->dev, "pclk clock not found.\n");
+ ret = PTR_ERR(xqspi->pclk);
+@@ -670,36 +659,24 @@ static int zynq_qspi_probe(struct platfo
+
+ init_completion(&xqspi->data_completion);
+
+- xqspi->refclk = devm_clk_get(&pdev->dev, "ref_clk");
++ xqspi->refclk = devm_clk_get_enabled(&pdev->dev, "ref_clk");
+ if (IS_ERR(xqspi->refclk)) {
+ dev_err(&pdev->dev, "ref_clk clock not found.\n");
+ ret = PTR_ERR(xqspi->refclk);
+ goto remove_ctlr;
+ }
+
+- ret = clk_prepare_enable(xqspi->pclk);
+- if (ret) {
+- dev_err(&pdev->dev, "Unable to enable APB clock.\n");
+- goto remove_ctlr;
+- }
+-
+- ret = clk_prepare_enable(xqspi->refclk);
+- if (ret) {
+- dev_err(&pdev->dev, "Unable to enable device clock.\n");
+- goto clk_dis_pclk;
+- }
+-
+ xqspi->irq = platform_get_irq(pdev, 0);
+ if (xqspi->irq < 0) {
+ ret = xqspi->irq;
+- goto clk_dis_all;
++ goto remove_ctlr;
+ }
+ ret = devm_request_irq(&pdev->dev, xqspi->irq, zynq_qspi_irq,
+ 0, pdev->name, xqspi);
+ if (ret != 0) {
+ ret = -ENXIO;
+ dev_err(&pdev->dev, "request_irq failed\n");
+- goto clk_dis_all;
++ goto remove_ctlr;
+ }
+
+ ret = of_property_read_u32(np, "num-cs",
+@@ -709,7 +686,7 @@ static int zynq_qspi_probe(struct platfo
+ } else if (num_cs > ZYNQ_QSPI_MAX_NUM_CS) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "only 2 chip selects are available\n");
+- goto clk_dis_all;
++ goto remove_ctlr;
+ } else {
+ ctlr->num_chipselect = num_cs;
+ }
+@@ -728,15 +705,11 @@ static int zynq_qspi_probe(struct platfo
+ ret = devm_spi_register_controller(&pdev->dev, ctlr);
+ if (ret) {
+ dev_err(&pdev->dev, "devm_spi_register_controller failed\n");
+- goto clk_dis_all;
++ goto remove_ctlr;
+ }
+
+ return ret;
+
+-clk_dis_all:
+- clk_disable_unprepare(xqspi->refclk);
+-clk_dis_pclk:
+- clk_disable_unprepare(xqspi->pclk);
+ remove_ctlr:
+ spi_controller_put(ctlr);
+
+@@ -758,9 +731,6 @@ static void zynq_qspi_remove(struct plat
+ struct zynq_qspi *xqspi = platform_get_drvdata(pdev);
+
+ zynq_qspi_write(xqspi, ZYNQ_QSPI_ENABLE_OFFSET, 0);
+-
+- clk_disable_unprepare(xqspi->refclk);
+- clk_disable_unprepare(xqspi->pclk);
+ }
+
+ static const struct of_device_id zynq_qspi_of_match[] = {
--- /dev/null
+From sashal@kernel.org Wed May 13 13:27:49 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 07:27:43 -0400
+Subject: usb: dwc3: Add dwc pointer to dwc3_readl/writel
+To: stable@vger.kernel.org
+Cc: Prashanth K <prashanth.k@oss.qualcomm.com>, Thinh Nguyen <Thinh.Nguyen@synopsys.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513112744.3646168-2-sashal@kernel.org>
+
+From: Prashanth K <prashanth.k@oss.qualcomm.com>
+
+[ Upstream commit 9accc68b1cf0a2b220f51d53641128bb32598070 ]
+
+Use dwc pointer in dwc3_readl() dwc3_writel() instead of passing
+the dwc->regs. This would help us access the dwc structure and
+log the base address in traces. There's no functional changes in
+this patch, just refactoring existing APIs.
+
+Signed-off-by: Prashanth K <prashanth.k@oss.qualcomm.com>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://patch.msgid.link/20260114100748.2950103-3-prashanth.k@oss.qualcomm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: aad35f9c926e ("usb: dwc3: Move GUID programming after PHY initialization")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/core.c | 194 ++++++++++++++++++++++-----------------------
+ drivers/usb/dwc3/debugfs.c | 32 +++----
+ drivers/usb/dwc3/drd.c | 76 ++++++++---------
+ drivers/usb/dwc3/ep0.c | 20 ++--
+ drivers/usb/dwc3/gadget.c | 160 ++++++++++++++++++-------------------
+ drivers/usb/dwc3/gadget.h | 4
+ drivers/usb/dwc3/io.h | 7 +
+ drivers/usb/dwc3/ulpi.c | 10 +-
+ 8 files changed, 253 insertions(+), 250 deletions(-)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -114,23 +114,23 @@ void dwc3_enable_susphy(struct dwc3 *dwc
+ int i;
+
+ for (i = 0; i < dwc->num_usb3_ports; i++) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(i));
++ reg = dwc3_readl(dwc, DWC3_GUSB3PIPECTL(i));
+ if (enable && !dwc->dis_u3_susphy_quirk)
+ reg |= DWC3_GUSB3PIPECTL_SUSPHY;
+ else
+ reg &= ~DWC3_GUSB3PIPECTL_SUSPHY;
+
+- dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(i), reg);
++ dwc3_writel(dwc, DWC3_GUSB3PIPECTL(i), reg);
+ }
+
+ for (i = 0; i < dwc->num_usb2_ports; i++) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(i));
+ if (enable && !dwc->dis_u2_susphy_quirk)
+ reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+ else
+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(i), reg);
+ }
+ }
+
+@@ -139,7 +139,7 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u
+ unsigned int hw_mode;
+ u32 reg;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GCTL);
++ reg = dwc3_readl(dwc, DWC3_GCTL);
+
+ /*
+ * For DRD controllers, GUSB3PIPECTL.SUSPENDENABLE and
+@@ -154,7 +154,7 @@ void dwc3_set_prtcap(struct dwc3 *dwc, u
+
+ reg &= ~(DWC3_GCTL_PRTCAPDIR(DWC3_GCTL_PRTCAP_OTG));
+ reg |= DWC3_GCTL_PRTCAPDIR(mode);
+- dwc3_writel(dwc->regs, DWC3_GCTL, reg);
++ dwc3_writel(dwc, DWC3_GCTL, reg);
+
+ dwc->current_dr_role = mode;
+ trace_dwc3_set_prtcap(mode);
+@@ -214,9 +214,9 @@ static void __dwc3_set_mode(struct work_
+ if (dwc->current_dr_role && ((DWC3_IP_IS(DWC3) ||
+ DWC3_VER_IS_PRIOR(DWC31, 190A)) &&
+ desired_dr_role != DWC3_GCTL_PRTCAP_OTG)) {
+- reg = dwc3_readl(dwc->regs, DWC3_GCTL);
++ reg = dwc3_readl(dwc, DWC3_GCTL);
+ reg |= DWC3_GCTL_CORESOFTRESET;
+- dwc3_writel(dwc->regs, DWC3_GCTL, reg);
++ dwc3_writel(dwc, DWC3_GCTL, reg);
+
+ /*
+ * Wait for internal clocks to synchronized. DWC_usb31 and
+@@ -226,9 +226,9 @@ static void __dwc3_set_mode(struct work_
+ */
+ msleep(100);
+
+- reg = dwc3_readl(dwc->regs, DWC3_GCTL);
++ reg = dwc3_readl(dwc, DWC3_GCTL);
+ reg &= ~DWC3_GCTL_CORESOFTRESET;
+- dwc3_writel(dwc->regs, DWC3_GCTL, reg);
++ dwc3_writel(dwc, DWC3_GCTL, reg);
+ }
+
+ spin_lock_irqsave(&dwc->lock, flags);
+@@ -252,9 +252,9 @@ static void __dwc3_set_mode(struct work_
+ phy_set_mode(dwc->usb3_generic_phy[i], PHY_MODE_USB_HOST);
+
+ if (dwc->dis_split_quirk) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
++ reg = dwc3_readl(dwc, DWC3_GUCTL3);
+ reg |= DWC3_GUCTL3_SPLITDISABLE;
+- dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
++ dwc3_writel(dwc, DWC3_GUCTL3, reg);
+ }
+ }
+ break;
+@@ -305,11 +305,11 @@ u32 dwc3_core_fifo_space(struct dwc3_ep
+ struct dwc3 *dwc = dep->dwc;
+ u32 reg;
+
+- dwc3_writel(dwc->regs, DWC3_GDBGFIFOSPACE,
+- DWC3_GDBGFIFOSPACE_NUM(dep->number) |
+- DWC3_GDBGFIFOSPACE_TYPE(type));
++ dwc3_writel(dwc, DWC3_GDBGFIFOSPACE,
++ DWC3_GDBGFIFOSPACE_NUM(dep->number) |
++ DWC3_GDBGFIFOSPACE_TYPE(type));
+
+- reg = dwc3_readl(dwc->regs, DWC3_GDBGFIFOSPACE);
++ reg = dwc3_readl(dwc, DWC3_GDBGFIFOSPACE);
+
+ return DWC3_GDBGFIFOSPACE_SPACE_AVAILABLE(reg);
+ }
+@@ -331,7 +331,7 @@ int dwc3_core_soft_reset(struct dwc3 *dw
+ if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST)
+ return 0;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ reg |= DWC3_DCTL_CSFTRST;
+ reg &= ~DWC3_DCTL_RUN_STOP;
+ dwc3_gadget_dctl_write_safe(dwc, reg);
+@@ -346,7 +346,7 @@ int dwc3_core_soft_reset(struct dwc3 *dw
+ retries = 10;
+
+ do {
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ if (!(reg & DWC3_DCTL_CSFTRST))
+ goto done;
+
+@@ -386,12 +386,12 @@ static void dwc3_frame_length_adjustment
+ if (dwc->fladj == 0)
+ return;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
++ reg = dwc3_readl(dwc, DWC3_GFLADJ);
+ dft = reg & DWC3_GFLADJ_30MHZ_MASK;
+ if (dft != dwc->fladj) {
+ reg &= ~DWC3_GFLADJ_30MHZ_MASK;
+ reg |= DWC3_GFLADJ_30MHZ_SDBND_SEL | dwc->fladj;
+- dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
++ dwc3_writel(dwc, DWC3_GFLADJ, reg);
+ }
+ }
+
+@@ -423,10 +423,10 @@ static void dwc3_ref_clk_period(struct d
+ return;
+ }
+
+- reg = dwc3_readl(dwc->regs, DWC3_GUCTL);
++ reg = dwc3_readl(dwc, DWC3_GUCTL);
+ reg &= ~DWC3_GUCTL_REFCLKPER_MASK;
+ reg |= FIELD_PREP(DWC3_GUCTL_REFCLKPER_MASK, period);
+- dwc3_writel(dwc->regs, DWC3_GUCTL, reg);
++ dwc3_writel(dwc, DWC3_GUCTL, reg);
+
+ if (DWC3_VER_IS_PRIOR(DWC3, 250A))
+ return;
+@@ -454,7 +454,7 @@ static void dwc3_ref_clk_period(struct d
+ */
+ decr = 480000000 / rate;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GFLADJ);
++ reg = dwc3_readl(dwc, DWC3_GFLADJ);
+ reg &= ~DWC3_GFLADJ_REFCLK_FLADJ_MASK
+ & ~DWC3_GFLADJ_240MHZDECR
+ & ~DWC3_GFLADJ_240MHZDECR_PLS1;
+@@ -465,7 +465,7 @@ static void dwc3_ref_clk_period(struct d
+ if (dwc->gfladj_refclk_lpm_sel)
+ reg |= DWC3_GFLADJ_REFCLK_LPM_SEL;
+
+- dwc3_writel(dwc->regs, DWC3_GFLADJ, reg);
++ dwc3_writel(dwc, DWC3_GFLADJ, reg);
+ }
+
+ /**
+@@ -568,16 +568,16 @@ int dwc3_event_buffers_setup(struct dwc3
+
+ evt = dwc->ev_buf;
+ evt->lpos = 0;
+- dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0),
+- lower_32_bits(evt->dma));
+- dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0),
+- upper_32_bits(evt->dma));
+- dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
+- DWC3_GEVNTSIZ_SIZE(evt->length));
++ dwc3_writel(dwc, DWC3_GEVNTADRLO(0),
++ lower_32_bits(evt->dma));
++ dwc3_writel(dwc, DWC3_GEVNTADRHI(0),
++ upper_32_bits(evt->dma));
++ dwc3_writel(dwc, DWC3_GEVNTSIZ(0),
++ DWC3_GEVNTSIZ_SIZE(evt->length));
+
+ /* Clear any stale event */
+- reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
+- dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg);
++ reg = dwc3_readl(dwc, DWC3_GEVNTCOUNT(0));
++ dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), reg);
+ return 0;
+ }
+
+@@ -592,7 +592,7 @@ void dwc3_event_buffers_cleanup(struct d
+ * Exynos platforms may not be able to access event buffer if the
+ * controller failed to halt on dwc3_core_exit().
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
++ reg = dwc3_readl(dwc, DWC3_DSTS);
+ if (!(reg & DWC3_DSTS_DEVCTRLHLT))
+ return;
+
+@@ -600,14 +600,14 @@ void dwc3_event_buffers_cleanup(struct d
+
+ evt->lpos = 0;
+
+- dwc3_writel(dwc->regs, DWC3_GEVNTADRLO(0), 0);
+- dwc3_writel(dwc->regs, DWC3_GEVNTADRHI(0), 0);
+- dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK
++ dwc3_writel(dwc, DWC3_GEVNTADRLO(0), 0);
++ dwc3_writel(dwc, DWC3_GEVNTADRHI(0), 0);
++ dwc3_writel(dwc, DWC3_GEVNTSIZ(0), DWC3_GEVNTSIZ_INTMASK
+ | DWC3_GEVNTSIZ_SIZE(0));
+
+ /* Clear any stale event */
+- reg = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
+- dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), reg);
++ reg = dwc3_readl(dwc, DWC3_GEVNTCOUNT(0));
++ dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), reg);
+ }
+
+ static void dwc3_core_num_eps(struct dwc3 *dwc)
+@@ -621,18 +621,18 @@ static void dwc3_cache_hwparams(struct d
+ {
+ struct dwc3_hwparams *parms = &dwc->hwparams;
+
+- parms->hwparams0 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS0);
+- parms->hwparams1 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS1);
+- parms->hwparams2 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS2);
+- parms->hwparams3 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS3);
+- parms->hwparams4 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS4);
+- parms->hwparams5 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS5);
+- parms->hwparams6 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS6);
+- parms->hwparams7 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS7);
+- parms->hwparams8 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS8);
++ parms->hwparams0 = dwc3_readl(dwc, DWC3_GHWPARAMS0);
++ parms->hwparams1 = dwc3_readl(dwc, DWC3_GHWPARAMS1);
++ parms->hwparams2 = dwc3_readl(dwc, DWC3_GHWPARAMS2);
++ parms->hwparams3 = dwc3_readl(dwc, DWC3_GHWPARAMS3);
++ parms->hwparams4 = dwc3_readl(dwc, DWC3_GHWPARAMS4);
++ parms->hwparams5 = dwc3_readl(dwc, DWC3_GHWPARAMS5);
++ parms->hwparams6 = dwc3_readl(dwc, DWC3_GHWPARAMS6);
++ parms->hwparams7 = dwc3_readl(dwc, DWC3_GHWPARAMS7);
++ parms->hwparams8 = dwc3_readl(dwc, DWC3_GHWPARAMS8);
+
+ if (DWC3_IP_IS(DWC32))
+- parms->hwparams9 = dwc3_readl(dwc->regs, DWC3_GHWPARAMS9);
++ parms->hwparams9 = dwc3_readl(dwc, DWC3_GHWPARAMS9);
+ }
+
+ static void dwc3_config_soc_bus(struct dwc3 *dwc)
+@@ -640,10 +640,10 @@ static void dwc3_config_soc_bus(struct d
+ if (dwc->gsbuscfg0_reqinfo != DWC3_GSBUSCFG0_REQINFO_UNSPECIFIED) {
+ u32 reg;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
++ reg = dwc3_readl(dwc, DWC3_GSBUSCFG0);
+ reg &= ~DWC3_GSBUSCFG0_REQINFO(~0);
+ reg |= DWC3_GSBUSCFG0_REQINFO(dwc->gsbuscfg0_reqinfo);
+- dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, reg);
++ dwc3_writel(dwc, DWC3_GSBUSCFG0, reg);
+ }
+ }
+
+@@ -667,7 +667,7 @@ static int dwc3_ss_phy_setup(struct dwc3
+ {
+ u32 reg;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(index));
++ reg = dwc3_readl(dwc, DWC3_GUSB3PIPECTL(index));
+
+ /*
+ * Make sure UX_EXIT_PX is cleared as that causes issues with some
+@@ -705,7 +705,7 @@ static int dwc3_ss_phy_setup(struct dwc3
+ if (dwc->dis_del_phy_power_chg_quirk)
+ reg &= ~DWC3_GUSB3PIPECTL_DEPOCHANGE;
+
+- dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(index), reg);
++ dwc3_writel(dwc, DWC3_GUSB3PIPECTL(index), reg);
+
+ return 0;
+ }
+@@ -714,7 +714,7 @@ static int dwc3_hs_phy_setup(struct dwc3
+ {
+ u32 reg;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(index));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(index));
+
+ /* Select the HS PHY interface */
+ switch (DWC3_GHWPARAMS3_HSPHY_IFC(dwc->hwparams.hwparams3)) {
+@@ -726,7 +726,7 @@ static int dwc3_hs_phy_setup(struct dwc3
+ } else if (dwc->hsphy_interface &&
+ !strncmp(dwc->hsphy_interface, "ulpi", 4)) {
+ reg |= DWC3_GUSB2PHYCFG_ULPI_UTMI;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(index), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(index), reg);
+ } else {
+ /* Relying on default value. */
+ if (!(reg & DWC3_GUSB2PHYCFG_ULPI_UTMI))
+@@ -776,7 +776,7 @@ static int dwc3_hs_phy_setup(struct dwc3
+ if (dwc->ulpi_ext_vbus_drv)
+ reg |= DWC3_GUSB2PHYCFG_ULPIEXTVBUSDRV;
+
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(index), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(index), reg);
+
+ return 0;
+ }
+@@ -989,7 +989,7 @@ static bool dwc3_core_is_valid(struct dw
+ {
+ u32 reg;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GSNPSID);
++ reg = dwc3_readl(dwc, DWC3_GSNPSID);
+ dwc->ip = DWC3_GSNPS_ID(reg);
+ if (dwc->ip == DWC4_IP)
+ dwc->ip = DWC32_IP;
+@@ -998,8 +998,8 @@ static bool dwc3_core_is_valid(struct dw
+ if (DWC3_IP_IS(DWC3)) {
+ dwc->revision = reg;
+ } else if (DWC3_IP_IS(DWC31) || DWC3_IP_IS(DWC32)) {
+- dwc->revision = dwc3_readl(dwc->regs, DWC3_VER_NUMBER);
+- dwc->version_type = dwc3_readl(dwc->regs, DWC3_VER_TYPE);
++ dwc->revision = dwc3_readl(dwc, DWC3_VER_NUMBER);
++ dwc->version_type = dwc3_readl(dwc, DWC3_VER_TYPE);
+ } else {
+ return false;
+ }
+@@ -1013,7 +1013,7 @@ static void dwc3_core_setup_global_contr
+ unsigned int hw_mode;
+ u32 reg;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GCTL);
++ reg = dwc3_readl(dwc, DWC3_GCTL);
+ reg &= ~DWC3_GCTL_SCALEDOWN_MASK;
+ hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
+ power_opt = DWC3_GHWPARAMS1_EN_PWROPT(dwc->hwparams.hwparams1);
+@@ -1091,7 +1091,7 @@ static void dwc3_core_setup_global_contr
+ if (DWC3_VER_IS_PRIOR(DWC3, 190A))
+ reg |= DWC3_GCTL_U2RSTECN;
+
+- dwc3_writel(dwc->regs, DWC3_GCTL, reg);
++ dwc3_writel(dwc, DWC3_GCTL, reg);
+ }
+
+ static int dwc3_core_get_phy(struct dwc3 *dwc);
+@@ -1111,7 +1111,7 @@ static void dwc3_set_incr_burst_type(str
+ int ret;
+ int i;
+
+- cfg = dwc3_readl(dwc->regs, DWC3_GSBUSCFG0);
++ cfg = dwc3_readl(dwc, DWC3_GSBUSCFG0);
+
+ /*
+ * Handle property "snps,incr-burst-type-adjustment".
+@@ -1186,7 +1186,7 @@ static void dwc3_set_incr_burst_type(str
+ break;
+ }
+
+- dwc3_writel(dwc->regs, DWC3_GSBUSCFG0, cfg);
++ dwc3_writel(dwc, DWC3_GSBUSCFG0, cfg);
+ }
+
+ static void dwc3_set_power_down_clk_scale(struct dwc3 *dwc)
+@@ -1211,12 +1211,12 @@ static void dwc3_set_power_down_clk_scal
+ * (3x or more) to be within the requirement.
+ */
+ scale = DIV_ROUND_UP(clk_get_rate(dwc->susp_clk), 16000);
+- reg = dwc3_readl(dwc->regs, DWC3_GCTL);
++ reg = dwc3_readl(dwc, DWC3_GCTL);
+ if ((reg & DWC3_GCTL_PWRDNSCALE_MASK) < DWC3_GCTL_PWRDNSCALE(scale) ||
+ (reg & DWC3_GCTL_PWRDNSCALE_MASK) > DWC3_GCTL_PWRDNSCALE(scale*3)) {
+ reg &= ~(DWC3_GCTL_PWRDNSCALE_MASK);
+ reg |= DWC3_GCTL_PWRDNSCALE(scale);
+- dwc3_writel(dwc->regs, DWC3_GCTL, reg);
++ dwc3_writel(dwc, DWC3_GCTL, reg);
+ }
+ }
+
+@@ -1239,7 +1239,7 @@ static void dwc3_config_threshold(struct
+ tx_maxburst = dwc->tx_max_burst_prd;
+
+ if (rx_thr_num && rx_maxburst) {
+- reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
++ reg = dwc3_readl(dwc, DWC3_GRXTHRCFG);
+ reg |= DWC31_RXTHRNUMPKTSEL_PRD;
+
+ reg &= ~DWC31_RXTHRNUMPKT_PRD(~0);
+@@ -1248,11 +1248,11 @@ static void dwc3_config_threshold(struct
+ reg &= ~DWC31_MAXRXBURSTSIZE_PRD(~0);
+ reg |= DWC31_MAXRXBURSTSIZE_PRD(rx_maxburst);
+
+- dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
++ dwc3_writel(dwc, DWC3_GRXTHRCFG, reg);
+ }
+
+ if (tx_thr_num && tx_maxburst) {
+- reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
++ reg = dwc3_readl(dwc, DWC3_GTXTHRCFG);
+ reg |= DWC31_TXTHRNUMPKTSEL_PRD;
+
+ reg &= ~DWC31_TXTHRNUMPKT_PRD(~0);
+@@ -1261,7 +1261,7 @@ static void dwc3_config_threshold(struct
+ reg &= ~DWC31_MAXTXBURSTSIZE_PRD(~0);
+ reg |= DWC31_MAXTXBURSTSIZE_PRD(tx_maxburst);
+
+- dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
++ dwc3_writel(dwc, DWC3_GTXTHRCFG, reg);
+ }
+ }
+
+@@ -1272,7 +1272,7 @@ static void dwc3_config_threshold(struct
+
+ if (DWC3_IP_IS(DWC3)) {
+ if (rx_thr_num && rx_maxburst) {
+- reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
++ reg = dwc3_readl(dwc, DWC3_GRXTHRCFG);
+ reg |= DWC3_GRXTHRCFG_PKTCNTSEL;
+
+ reg &= ~DWC3_GRXTHRCFG_RXPKTCNT(~0);
+@@ -1281,11 +1281,11 @@ static void dwc3_config_threshold(struct
+ reg &= ~DWC3_GRXTHRCFG_MAXRXBURSTSIZE(~0);
+ reg |= DWC3_GRXTHRCFG_MAXRXBURSTSIZE(rx_maxburst);
+
+- dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
++ dwc3_writel(dwc, DWC3_GRXTHRCFG, reg);
+ }
+
+ if (tx_thr_num && tx_maxburst) {
+- reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
++ reg = dwc3_readl(dwc, DWC3_GTXTHRCFG);
+ reg |= DWC3_GTXTHRCFG_PKTCNTSEL;
+
+ reg &= ~DWC3_GTXTHRCFG_TXPKTCNT(~0);
+@@ -1294,11 +1294,11 @@ static void dwc3_config_threshold(struct
+ reg &= ~DWC3_GTXTHRCFG_MAXTXBURSTSIZE(~0);
+ reg |= DWC3_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst);
+
+- dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
++ dwc3_writel(dwc, DWC3_GTXTHRCFG, reg);
+ }
+ } else {
+ if (rx_thr_num && rx_maxburst) {
+- reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
++ reg = dwc3_readl(dwc, DWC3_GRXTHRCFG);
+ reg |= DWC31_GRXTHRCFG_PKTCNTSEL;
+
+ reg &= ~DWC31_GRXTHRCFG_RXPKTCNT(~0);
+@@ -1307,11 +1307,11 @@ static void dwc3_config_threshold(struct
+ reg &= ~DWC31_GRXTHRCFG_MAXRXBURSTSIZE(~0);
+ reg |= DWC31_GRXTHRCFG_MAXRXBURSTSIZE(rx_maxburst);
+
+- dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
++ dwc3_writel(dwc, DWC3_GRXTHRCFG, reg);
+ }
+
+ if (tx_thr_num && tx_maxburst) {
+- reg = dwc3_readl(dwc->regs, DWC3_GTXTHRCFG);
++ reg = dwc3_readl(dwc, DWC3_GTXTHRCFG);
+ reg |= DWC31_GTXTHRCFG_PKTCNTSEL;
+
+ reg &= ~DWC31_GTXTHRCFG_TXPKTCNT(~0);
+@@ -1320,7 +1320,7 @@ static void dwc3_config_threshold(struct
+ reg &= ~DWC31_GTXTHRCFG_MAXTXBURSTSIZE(~0);
+ reg |= DWC31_GTXTHRCFG_MAXTXBURSTSIZE(tx_maxburst);
+
+- dwc3_writel(dwc->regs, DWC3_GTXTHRCFG, reg);
++ dwc3_writel(dwc, DWC3_GTXTHRCFG, reg);
+ }
+ }
+ }
+@@ -1343,7 +1343,7 @@ static int dwc3_core_init(struct dwc3 *d
+ * Write Linux Version Code to our GUID register so it's easy to figure
+ * out which kernel version a bug was found.
+ */
+- dwc3_writel(dwc->regs, DWC3_GUID, LINUX_VERSION_CODE);
++ dwc3_writel(dwc, DWC3_GUID, LINUX_VERSION_CODE);
+
+ ret = dwc3_phy_setup(dwc);
+ if (ret)
+@@ -1408,9 +1408,9 @@ static int dwc3_core_init(struct dwc3 *d
+ * DWC_usb31 controller.
+ */
+ if (DWC3_VER_IS_WITHIN(DWC3, 310A, ANY)) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUCTL2);
++ reg = dwc3_readl(dwc, DWC3_GUCTL2);
+ reg |= DWC3_GUCTL2_RST_ACTBITLATER;
+- dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
++ dwc3_writel(dwc, DWC3_GUCTL2, reg);
+ }
+
+ /*
+@@ -1423,9 +1423,9 @@ static int dwc3_core_init(struct dwc3 *d
+ * setting GUCTL2[19] by default; instead, use GUCTL2[19] = 0.
+ */
+ if (DWC3_VER_IS(DWC3, 320A)) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUCTL2);
++ reg = dwc3_readl(dwc, DWC3_GUCTL2);
+ reg &= ~DWC3_GUCTL2_LC_TIMER;
+- dwc3_writel(dwc->regs, DWC3_GUCTL2, reg);
++ dwc3_writel(dwc, DWC3_GUCTL2, reg);
+ }
+
+ /*
+@@ -1438,13 +1438,13 @@ static int dwc3_core_init(struct dwc3 *d
+ * legacy ULPI PHYs.
+ */
+ if (dwc->resume_hs_terminations) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
++ reg = dwc3_readl(dwc, DWC3_GUCTL1);
+ reg |= DWC3_GUCTL1_RESUME_OPMODE_HS_HOST;
+- dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
++ dwc3_writel(dwc, DWC3_GUCTL1, reg);
+ }
+
+ if (!DWC3_VER_IS_PRIOR(DWC3, 250A)) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUCTL1);
++ reg = dwc3_readl(dwc, DWC3_GUCTL1);
+
+ /*
+ * Enable hardware control of sending remote wakeup
+@@ -1479,7 +1479,7 @@ static int dwc3_core_init(struct dwc3 *d
+ reg &= ~DWC3_GUCTL1_DEV_FORCE_20_CLK_FOR_30_CLK;
+ }
+
+- dwc3_writel(dwc->regs, DWC3_GUCTL1, reg);
++ dwc3_writel(dwc, DWC3_GUCTL1, reg);
+ }
+
+ dwc3_config_threshold(dwc);
+@@ -1494,9 +1494,9 @@ static int dwc3_core_init(struct dwc3 *d
+ int i;
+
+ for (i = 0; i < dwc->num_usb3_ports; i++) {
+- reg = dwc3_readl(dwc->regs, DWC3_LLUCTL(i));
++ reg = dwc3_readl(dwc, DWC3_LLUCTL(i));
+ reg |= DWC3_LLUCTL_FORCE_GEN1;
+- dwc3_writel(dwc->regs, DWC3_LLUCTL(i), reg);
++ dwc3_writel(dwc, DWC3_LLUCTL(i), reg);
+ }
+ }
+
+@@ -1515,9 +1515,9 @@ static int dwc3_core_init(struct dwc3 *d
+ * function is available only from version 1.70a.
+ */
+ if (DWC3_VER_IS_WITHIN(DWC31, 170A, 180A)) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
++ reg = dwc3_readl(dwc, DWC3_GUCTL3);
+ reg |= DWC3_GUCTL3_USB20_RETRY_DISABLE;
+- dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
++ dwc3_writel(dwc, DWC3_GUCTL3, reg);
+ }
+
+ return 0;
+@@ -2447,9 +2447,9 @@ static int dwc3_suspend_common(struct dw
+ int ret;
+
+ if (!pm_runtime_suspended(dwc->dev) && !PMSG_IS_AUTO(msg)) {
+- dwc->susphy_state = (dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0)) &
++ dwc->susphy_state = (dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0)) &
+ DWC3_GUSB2PHYCFG_SUSPHY) ||
+- (dwc3_readl(dwc->regs, DWC3_GUSB3PIPECTL(0)) &
++ (dwc3_readl(dwc, DWC3_GUSB3PIPECTL(0)) &
+ DWC3_GUSB3PIPECTL_SUSPHY);
+ /*
+ * TI AM62 platform requires SUSPHY to be
+@@ -2479,10 +2479,10 @@ static int dwc3_suspend_common(struct dw
+ if (dwc->dis_u2_susphy_quirk ||
+ dwc->dis_enblslpm_quirk) {
+ for (i = 0; i < dwc->num_usb2_ports; i++) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(i));
+ reg |= DWC3_GUSB2PHYCFG_ENBLSLPM |
+ DWC3_GUSB2PHYCFG_SUSPHY;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(i), reg);
+ }
+
+ /* Give some time for USB2 PHY to suspend */
+@@ -2542,14 +2542,14 @@ static int dwc3_resume_common(struct dwc
+ }
+ /* Restore GUSB2PHYCFG bits that were modified in suspend */
+ for (i = 0; i < dwc->num_usb2_ports; i++) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(i));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(i));
+ if (dwc->dis_u2_susphy_quirk)
+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+
+ if (dwc->dis_enblslpm_quirk)
+ reg &= ~DWC3_GUSB2PHYCFG_ENBLSLPM;
+
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(i), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(i), reg);
+ }
+
+ for (i = 0; i < dwc->num_usb2_ports; i++)
+@@ -2732,9 +2732,9 @@ void dwc3_pm_complete(struct dwc3 *dwc)
+
+ if (dwc->current_dr_role == DWC3_GCTL_PRTCAP_HOST &&
+ dwc->dis_split_quirk) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUCTL3);
++ reg = dwc3_readl(dwc, DWC3_GUCTL3);
+ reg |= DWC3_GUCTL3_SPLITDISABLE;
+- dwc3_writel(dwc->regs, DWC3_GUCTL3, reg);
++ dwc3_writel(dwc, DWC3_GUCTL3, reg);
+ }
+ }
+ EXPORT_SYMBOL_GPL(dwc3_pm_complete);
+--- a/drivers/usb/dwc3/debugfs.c
++++ b/drivers/usb/dwc3/debugfs.c
+@@ -296,14 +296,14 @@ static void dwc3_host_lsp(struct seq_fil
+
+ reg = DWC3_GDBGLSPMUX_HOSTSELECT(sel);
+
+- dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg);
+- val = dwc3_readl(dwc->regs, DWC3_GDBGLSP);
++ dwc3_writel(dwc, DWC3_GDBGLSPMUX, reg);
++ val = dwc3_readl(dwc, DWC3_GDBGLSP);
+ seq_printf(s, "GDBGLSP[%d] = 0x%08x\n", sel, val);
+
+ if (dbc_enabled && sel < 256) {
+ reg |= DWC3_GDBGLSPMUX_ENDBC;
+- dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg);
+- val = dwc3_readl(dwc->regs, DWC3_GDBGLSP);
++ dwc3_writel(dwc, DWC3_GDBGLSPMUX, reg);
++ val = dwc3_readl(dwc, DWC3_GDBGLSP);
+ seq_printf(s, "GDBGLSP_DBC[%d] = 0x%08x\n", sel, val);
+ }
+ }
+@@ -316,8 +316,8 @@ static void dwc3_gadget_lsp(struct seq_f
+
+ for (i = 0; i < 16; i++) {
+ reg = DWC3_GDBGLSPMUX_DEVSELECT(i);
+- dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg);
+- reg = dwc3_readl(dwc->regs, DWC3_GDBGLSP);
++ dwc3_writel(dwc, DWC3_GDBGLSPMUX, reg);
++ reg = dwc3_readl(dwc, DWC3_GDBGLSP);
+ seq_printf(s, "GDBGLSP[%d] = 0x%08x\n", i, reg);
+ }
+ }
+@@ -335,7 +335,7 @@ static int dwc3_lsp_show(struct seq_file
+ return ret;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+- reg = dwc3_readl(dwc->regs, DWC3_GSTS);
++ reg = dwc3_readl(dwc, DWC3_GSTS);
+ current_mode = DWC3_GSTS_CURMOD(reg);
+
+ switch (current_mode) {
+@@ -406,7 +406,7 @@ static int dwc3_mode_show(struct seq_fil
+ return ret;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+- reg = dwc3_readl(dwc->regs, DWC3_GCTL);
++ reg = dwc3_readl(dwc, DWC3_GCTL);
+ spin_unlock_irqrestore(&dwc->lock, flags);
+
+ mode = DWC3_GCTL_PRTCAP(reg);
+@@ -478,7 +478,7 @@ static int dwc3_testmode_show(struct seq
+ return ret;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ reg &= DWC3_DCTL_TSTCTRL_MASK;
+ reg >>= 1;
+ spin_unlock_irqrestore(&dwc->lock, flags);
+@@ -577,7 +577,7 @@ static int dwc3_link_state_show(struct s
+ return ret;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+- reg = dwc3_readl(dwc->regs, DWC3_GSTS);
++ reg = dwc3_readl(dwc, DWC3_GSTS);
+ if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) {
+ seq_puts(s, "Not available\n");
+ spin_unlock_irqrestore(&dwc->lock, flags);
+@@ -585,7 +585,7 @@ static int dwc3_link_state_show(struct s
+ return 0;
+ }
+
+- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
++ reg = dwc3_readl(dwc, DWC3_DSTS);
+ state = DWC3_DSTS_USBLNKST(reg);
+ speed = reg & DWC3_DSTS_CONNECTSPD;
+
+@@ -639,14 +639,14 @@ static ssize_t dwc3_link_state_write(str
+ return ret;
+
+ spin_lock_irqsave(&dwc->lock, flags);
+- reg = dwc3_readl(dwc->regs, DWC3_GSTS);
++ reg = dwc3_readl(dwc, DWC3_GSTS);
+ if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) {
+ spin_unlock_irqrestore(&dwc->lock, flags);
+ pm_runtime_put_sync(dwc->dev);
+ return -EINVAL;
+ }
+
+- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
++ reg = dwc3_readl(dwc, DWC3_DSTS);
+ speed = reg & DWC3_DSTS_CONNECTSPD;
+
+ if (speed < DWC3_DSTS_SUPERSPEED &&
+@@ -942,10 +942,10 @@ static int dwc3_ep_info_register_show(st
+
+ spin_lock_irqsave(&dwc->lock, flags);
+ reg = DWC3_GDBGLSPMUX_EPSELECT(dep->number);
+- dwc3_writel(dwc->regs, DWC3_GDBGLSPMUX, reg);
++ dwc3_writel(dwc, DWC3_GDBGLSPMUX, reg);
+
+- lower_32_bits = dwc3_readl(dwc->regs, DWC3_GDBGEPINFO0);
+- upper_32_bits = dwc3_readl(dwc->regs, DWC3_GDBGEPINFO1);
++ lower_32_bits = dwc3_readl(dwc, DWC3_GDBGEPINFO0);
++ upper_32_bits = dwc3_readl(dwc, DWC3_GDBGEPINFO1);
+
+ ep_info = ((u64)upper_32_bits << 32) | lower_32_bits;
+ seq_printf(s, "0x%016llx\n", ep_info);
+--- a/drivers/usb/dwc3/drd.c
++++ b/drivers/usb/dwc3/drd.c
+@@ -18,25 +18,25 @@
+
+ static void dwc3_otg_disable_events(struct dwc3 *dwc, u32 disable_mask)
+ {
+- u32 reg = dwc3_readl(dwc->regs, DWC3_OEVTEN);
++ u32 reg = dwc3_readl(dwc, DWC3_OEVTEN);
+
+ reg &= ~(disable_mask);
+- dwc3_writel(dwc->regs, DWC3_OEVTEN, reg);
++ dwc3_writel(dwc, DWC3_OEVTEN, reg);
+ }
+
+ static void dwc3_otg_enable_events(struct dwc3 *dwc, u32 enable_mask)
+ {
+- u32 reg = dwc3_readl(dwc->regs, DWC3_OEVTEN);
++ u32 reg = dwc3_readl(dwc, DWC3_OEVTEN);
+
+ reg |= (enable_mask);
+- dwc3_writel(dwc->regs, DWC3_OEVTEN, reg);
++ dwc3_writel(dwc, DWC3_OEVTEN, reg);
+ }
+
+ static void dwc3_otg_clear_events(struct dwc3 *dwc)
+ {
+- u32 reg = dwc3_readl(dwc->regs, DWC3_OEVT);
++ u32 reg = dwc3_readl(dwc, DWC3_OEVT);
+
+- dwc3_writel(dwc->regs, DWC3_OEVTEN, reg);
++ dwc3_writel(dwc, DWC3_OEVTEN, reg);
+ }
+
+ #define DWC3_OTG_ALL_EVENTS (DWC3_OEVTEN_XHCIRUNSTPSETEN | \
+@@ -72,18 +72,18 @@ static irqreturn_t dwc3_otg_irq(int irq,
+ struct dwc3 *dwc = _dwc;
+ irqreturn_t ret = IRQ_NONE;
+
+- reg = dwc3_readl(dwc->regs, DWC3_OEVT);
++ reg = dwc3_readl(dwc, DWC3_OEVT);
+ if (reg) {
+ /* ignore non OTG events, we can't disable them in OEVTEN */
+ if (!(reg & DWC3_OTG_ALL_EVENTS)) {
+- dwc3_writel(dwc->regs, DWC3_OEVT, reg);
++ dwc3_writel(dwc, DWC3_OEVT, reg);
+ return IRQ_NONE;
+ }
+
+ if (dwc->current_otg_role == DWC3_OTG_ROLE_HOST &&
+ !(reg & DWC3_OEVT_DEVICEMODE))
+ dwc->otg_restart_host = true;
+- dwc3_writel(dwc->regs, DWC3_OEVT, reg);
++ dwc3_writel(dwc, DWC3_OEVT, reg);
+ ret = IRQ_WAKE_THREAD;
+ }
+
+@@ -100,23 +100,23 @@ static void dwc3_otgregs_init(struct dwc
+ * the signal outputs sent to the PHY, the OTG FSM logic of the
+ * core and also the resets to the VBUS filters inside the core.
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_OCFG);
++ reg = dwc3_readl(dwc, DWC3_OCFG);
+ reg |= DWC3_OCFG_SFTRSTMASK;
+- dwc3_writel(dwc->regs, DWC3_OCFG, reg);
++ dwc3_writel(dwc, DWC3_OCFG, reg);
+
+ /* Disable hibernation for simplicity */
+- reg = dwc3_readl(dwc->regs, DWC3_GCTL);
++ reg = dwc3_readl(dwc, DWC3_GCTL);
+ reg &= ~DWC3_GCTL_GBLHIBERNATIONEN;
+- dwc3_writel(dwc->regs, DWC3_GCTL, reg);
++ dwc3_writel(dwc, DWC3_GCTL, reg);
+
+ /*
+ * Initialize OTG registers as per
+ * Figure 11-4 OTG Driver Overall Programming Flow
+ */
+ /* OCFG.SRPCap = 0, OCFG.HNPCap = 0 */
+- reg = dwc3_readl(dwc->regs, DWC3_OCFG);
++ reg = dwc3_readl(dwc, DWC3_OCFG);
+ reg &= ~(DWC3_OCFG_SRPCAP | DWC3_OCFG_HNPCAP);
+- dwc3_writel(dwc->regs, DWC3_OCFG, reg);
++ dwc3_writel(dwc, DWC3_OCFG, reg);
+ /* OEVT = FFFF */
+ dwc3_otg_clear_events(dwc);
+ /* OEVTEN = 0 */
+@@ -127,11 +127,11 @@ static void dwc3_otgregs_init(struct dwc
+ * OCTL.PeriMode = 1, OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0,
+ * OCTL.HNPReq = 0
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_OCTL);
++ reg = dwc3_readl(dwc, DWC3_OCTL);
+ reg |= DWC3_OCTL_PERIMODE;
+ reg &= ~(DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN |
+ DWC3_OCTL_HNPREQ);
+- dwc3_writel(dwc->regs, DWC3_OCTL, reg);
++ dwc3_writel(dwc, DWC3_OCTL, reg);
+ }
+
+ static int dwc3_otg_get_irq(struct dwc3 *dwc)
+@@ -175,9 +175,9 @@ void dwc3_otg_init(struct dwc3 *dwc)
+ /* GCTL.PrtCapDir=2'b11 */
+ dwc3_set_prtcap(dwc, DWC3_GCTL_PRTCAP_OTG, true);
+ /* GUSB2PHYCFG0.SusPHY=0 */
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0));
+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg);
+
+ /* Initialize OTG registers */
+ dwc3_otgregs_init(dwc);
+@@ -203,17 +203,17 @@ void dwc3_otg_host_init(struct dwc3 *dwc
+ * OCTL.PeriMode=0, OCTL.TermSelDLPulse = 0,
+ * OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_OCTL);
++ reg = dwc3_readl(dwc, DWC3_OCTL);
+ reg &= ~(DWC3_OCTL_PERIMODE | DWC3_OCTL_TERMSELIDPULSE |
+ DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN);
+- dwc3_writel(dwc->regs, DWC3_OCTL, reg);
++ dwc3_writel(dwc, DWC3_OCTL, reg);
+
+ /*
+ * OCFG.DisPrtPwrCutoff = 0/1
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_OCFG);
++ reg = dwc3_readl(dwc, DWC3_OCFG);
+ reg &= ~DWC3_OCFG_DISPWRCUTTOFF;
+- dwc3_writel(dwc->regs, DWC3_OCFG, reg);
++ dwc3_writel(dwc, DWC3_OCFG, reg);
+
+ /*
+ * OCFG.SRPCap = 1, OCFG.HNPCap = GHWPARAMS6.HNP_CAP
+@@ -229,15 +229,15 @@ void dwc3_otg_host_init(struct dwc3 *dwc
+
+ /* GUSB2PHYCFG.ULPIAutoRes = 1/0, GUSB2PHYCFG.SusPHY = 1 */
+ if (!dwc->dis_u2_susphy_quirk) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0));
+ reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg);
+ }
+
+ /* Set Port Power to enable VBUS: OCTL.PrtPwrCtl = 1 */
+- reg = dwc3_readl(dwc->regs, DWC3_OCTL);
++ reg = dwc3_readl(dwc, DWC3_OCTL);
+ reg |= DWC3_OCTL_PRTPWRCTL;
+- dwc3_writel(dwc->regs, DWC3_OCTL, reg);
++ dwc3_writel(dwc, DWC3_OCTL, reg);
+ }
+
+ /* should be called after Host controller driver is stopped */
+@@ -258,9 +258,9 @@ static void dwc3_otg_host_exit(struct dw
+ */
+
+ /* OCTL.HstSetHNPEn = 0, OCTL.PrtPwrCtl=0 */
+- reg = dwc3_readl(dwc->regs, DWC3_OCTL);
++ reg = dwc3_readl(dwc, DWC3_OCTL);
+ reg &= ~(DWC3_OCTL_HSTSETHNPEN | DWC3_OCTL_PRTPWRCTL);
+- dwc3_writel(dwc->regs, DWC3_OCTL, reg);
++ dwc3_writel(dwc, DWC3_OCTL, reg);
+ }
+
+ /* should be called before the gadget controller driver is started */
+@@ -274,27 +274,27 @@ static void dwc3_otg_device_init(struct
+ * OCFG.HNPCap = GHWPARAMS6.HNP_CAP, OCFG.SRPCap = 1
+ * but we keep them 0 for simple dual-role operation.
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_OCFG);
++ reg = dwc3_readl(dwc, DWC3_OCFG);
+ /* OCFG.OTGSftRstMsk = 0/1 */
+ reg |= DWC3_OCFG_SFTRSTMASK;
+- dwc3_writel(dwc->regs, DWC3_OCFG, reg);
++ dwc3_writel(dwc, DWC3_OCFG, reg);
+ /*
+ * OCTL.PeriMode = 1
+ * OCTL.TermSelDLPulse = 0/1, OCTL.HNPReq = 0
+ * OCTL.DevSetHNPEn = 0, OCTL.HstSetHNPEn = 0
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_OCTL);
++ reg = dwc3_readl(dwc, DWC3_OCTL);
+ reg |= DWC3_OCTL_PERIMODE;
+ reg &= ~(DWC3_OCTL_TERMSELIDPULSE | DWC3_OCTL_HNPREQ |
+ DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HSTSETHNPEN);
+- dwc3_writel(dwc->regs, DWC3_OCTL, reg);
++ dwc3_writel(dwc, DWC3_OCTL, reg);
+ /* OEVTEN.OTGBDevSesVldDetEvntEn = 1 */
+ dwc3_otg_enable_events(dwc, DWC3_OEVTEN_BDEVSESSVLDDETEN);
+ /* GUSB2PHYCFG.ULPIAutoRes = 0, GUSB2PHYCFG0.SusPHY = 1 */
+ if (!dwc->dis_u2_susphy_quirk) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0));
+ reg |= DWC3_GUSB2PHYCFG_SUSPHY;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg);
+ }
+ /* GCTL.GblHibernationEn = 0. Already 0. */
+ }
+@@ -319,10 +319,10 @@ static void dwc3_otg_device_exit(struct
+ DWC3_OEVTEN_BDEVBHOSTENDEN);
+
+ /* OCTL.DevSetHNPEn = 0, OCTL.HNPReq = 0, OCTL.PeriMode=1 */
+- reg = dwc3_readl(dwc->regs, DWC3_OCTL);
++ reg = dwc3_readl(dwc, DWC3_OCTL);
+ reg &= ~(DWC3_OCTL_DEVSETHNPEN | DWC3_OCTL_HNPREQ);
+ reg |= DWC3_OCTL_PERIMODE;
+- dwc3_writel(dwc->regs, DWC3_OCTL, reg);
++ dwc3_writel(dwc, DWC3_OCTL, reg);
+ }
+
+ void dwc3_otg_update(struct dwc3 *dwc, bool ignore_idstatus)
+@@ -341,7 +341,7 @@ void dwc3_otg_update(struct dwc3 *dwc, b
+ return;
+
+ if (!ignore_idstatus) {
+- reg = dwc3_readl(dwc->regs, DWC3_OSTS);
++ reg = dwc3_readl(dwc, DWC3_OSTS);
+ id = !!(reg & DWC3_OSTS_CONIDSTS);
+
+ dwc->desired_otg_role = id ? DWC3_OTG_ROLE_DEVICE :
+--- a/drivers/usb/dwc3/ep0.c
++++ b/drivers/usb/dwc3/ep0.c
+@@ -361,7 +361,7 @@ static int dwc3_ep0_handle_status(struct
+
+ if ((dwc->speed == DWC3_DSTS_SUPERSPEED) ||
+ (dwc->speed == DWC3_DSTS_SUPERSPEED_PLUS)) {
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ if (reg & DWC3_DCTL_INITU1ENA)
+ usb_status |= 1 << USB_DEV_STAT_U1_ENABLED;
+ if (reg & DWC3_DCTL_INITU2ENA)
+@@ -417,12 +417,12 @@ static int dwc3_ep0_handle_u1(struct dwc
+ if (set && dwc->dis_u1_entry_quirk)
+ return -EINVAL;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ if (set)
+ reg |= DWC3_DCTL_INITU1ENA;
+ else
+ reg &= ~DWC3_DCTL_INITU1ENA;
+- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
++ dwc3_writel(dwc, DWC3_DCTL, reg);
+
+ return 0;
+ }
+@@ -441,12 +441,12 @@ static int dwc3_ep0_handle_u2(struct dwc
+ if (set && dwc->dis_u2_entry_quirk)
+ return -EINVAL;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ if (set)
+ reg |= DWC3_DCTL_INITU2ENA;
+ else
+ reg &= ~DWC3_DCTL_INITU2ENA;
+- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
++ dwc3_writel(dwc, DWC3_DCTL, reg);
+
+ return 0;
+ }
+@@ -612,10 +612,10 @@ static int dwc3_ep0_set_address(struct d
+ return -EINVAL;
+ }
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCFG);
++ reg = dwc3_readl(dwc, DWC3_DCFG);
+ reg &= ~(DWC3_DCFG_DEVADDR_MASK);
+ reg |= DWC3_DCFG_DEVADDR(addr);
+- dwc3_writel(dwc->regs, DWC3_DCFG, reg);
++ dwc3_writel(dwc, DWC3_DCFG, reg);
+
+ if (addr)
+ usb_gadget_set_state(dwc->gadget, USB_STATE_ADDRESS);
+@@ -672,12 +672,12 @@ static int dwc3_ep0_set_config(struct dw
+ * Enable transition to U1/U2 state when
+ * nothing is pending from application.
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ if (!dwc->dis_u1_entry_quirk)
+ reg |= DWC3_DCTL_ACCEPTU1ENA;
+ if (!dwc->dis_u2_entry_quirk)
+ reg |= DWC3_DCTL_ACCEPTU2ENA;
+- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
++ dwc3_writel(dwc, DWC3_DCTL, reg);
+ }
+ break;
+
+@@ -717,7 +717,7 @@ static void dwc3_ep0_set_sel_cmpl(struct
+ dwc->u2sel = le16_to_cpu(timing.u2sel);
+ dwc->u2pel = le16_to_cpu(timing.u2pel);
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ if (reg & DWC3_DCTL_INITU2ENA)
+ param = dwc->u2pel;
+ if (reg & DWC3_DCTL_INITU1ENA)
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -42,7 +42,7 @@ int dwc3_gadget_set_test_mode(struct dwc
+ {
+ u32 reg;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ reg &= ~DWC3_DCTL_TSTCTRL_MASK;
+
+ switch (mode) {
+@@ -73,7 +73,7 @@ int dwc3_gadget_get_link_state(struct dw
+ {
+ u32 reg;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
++ reg = dwc3_readl(dwc, DWC3_DSTS);
+
+ return DWC3_DSTS_USBLNKST(reg);
+ }
+@@ -97,7 +97,7 @@ int dwc3_gadget_set_link_state(struct dw
+ */
+ if (!DWC3_VER_IS_PRIOR(DWC3, 194A)) {
+ while (--retries) {
+- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
++ reg = dwc3_readl(dwc, DWC3_DSTS);
+ if (reg & DWC3_DSTS_DCNRD)
+ udelay(5);
+ else
+@@ -108,15 +108,15 @@ int dwc3_gadget_set_link_state(struct dw
+ return -ETIMEDOUT;
+ }
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
+
+ /* set no action before sending new link state change */
+- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
++ dwc3_writel(dwc, DWC3_DCTL, reg);
+
+ /* set requested state */
+ reg |= DWC3_DCTL_ULSTCHNGREQ(state);
+- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
++ dwc3_writel(dwc, DWC3_DCTL, reg);
+
+ /*
+ * The following code is racy when called from dwc3_gadget_wakeup,
+@@ -128,7 +128,7 @@ int dwc3_gadget_set_link_state(struct dw
+ /* wait for a change in DSTS */
+ retries = 10000;
+ while (--retries) {
+- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
++ reg = dwc3_readl(dwc, DWC3_DSTS);
+
+ if (DWC3_DSTS_USBLNKST(reg) == state)
+ return 0;
+@@ -260,11 +260,11 @@ int dwc3_send_gadget_generic_command(str
+ int ret = 0;
+ u32 reg;
+
+- dwc3_writel(dwc->regs, DWC3_DGCMDPAR, param);
+- dwc3_writel(dwc->regs, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);
++ dwc3_writel(dwc, DWC3_DGCMDPAR, param);
++ dwc3_writel(dwc, DWC3_DGCMD, cmd | DWC3_DGCMD_CMDACT);
+
+ do {
+- reg = dwc3_readl(dwc->regs, DWC3_DGCMD);
++ reg = dwc3_readl(dwc, DWC3_DGCMD);
+ if (!(reg & DWC3_DGCMD_CMDACT)) {
+ status = DWC3_DGCMD_STATUS(reg);
+ if (status)
+@@ -334,7 +334,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_
+ */
+ if (dwc->gadget->speed <= USB_SPEED_HIGH ||
+ DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0));
+ if (unlikely(reg & DWC3_GUSB2PHYCFG_SUSPHY)) {
+ saved_config |= DWC3_GUSB2PHYCFG_SUSPHY;
+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+@@ -346,7 +346,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_
+ }
+
+ if (saved_config)
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg);
+ }
+
+ /*
+@@ -356,9 +356,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_
+ * improve performance.
+ */
+ if (DWC3_DEPCMD_CMD(cmd) != DWC3_DEPCMD_UPDATETRANSFER) {
+- dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(epnum), params->param0);
+- dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(epnum), params->param1);
+- dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(epnum), params->param2);
++ dwc3_writel(dwc, DWC3_DEPCMDPAR0(epnum), params->param0);
++ dwc3_writel(dwc, DWC3_DEPCMDPAR1(epnum), params->param1);
++ dwc3_writel(dwc, DWC3_DEPCMDPAR2(epnum), params->param2);
+ }
+
+ /*
+@@ -382,7 +382,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_
+ else
+ cmd |= DWC3_DEPCMD_CMDACT;
+
+- dwc3_writel(dwc->regs, DWC3_DEPCMD(epnum), cmd);
++ dwc3_writel(dwc, DWC3_DEPCMD(epnum), cmd);
+
+ if (!(cmd & DWC3_DEPCMD_CMDACT) ||
+ (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER &&
+@@ -392,7 +392,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_
+ }
+
+ do {
+- reg = dwc3_readl(dwc->regs, DWC3_DEPCMD(epnum));
++ reg = dwc3_readl(dwc, DWC3_DEPCMD(epnum));
+ if (!(reg & DWC3_DEPCMD_CMDACT)) {
+ cmd_status = DWC3_DEPCMD_STATUS(reg);
+
+@@ -448,9 +448,9 @@ skip_status:
+ mdelay(1);
+
+ if (saved_config) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0));
+ reg |= saved_config;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg);
+ }
+
+ return ret;
+@@ -727,7 +727,7 @@ static int dwc3_gadget_calc_ram_depth(st
+ u32 reg;
+
+ /* Check if TXFIFOs start at non-zero addr */
+- reg = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
++ reg = dwc3_readl(dwc, DWC3_GTXFIFOSIZ(0));
+ fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(reg);
+
+ ram_depth -= (fifo_0_start >> 16);
+@@ -755,7 +755,7 @@ void dwc3_gadget_clear_tx_fifos(struct d
+
+ /* Read ep0IN related TXFIFO size */
+ dep = dwc->eps[1];
+- size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
++ size = dwc3_readl(dwc, DWC3_GTXFIFOSIZ(0));
+ if (DWC3_IP_IS(DWC3))
+ fifo_depth = DWC3_GTXFIFOSIZ_TXFDEP(size);
+ else
+@@ -770,10 +770,10 @@ void dwc3_gadget_clear_tx_fifos(struct d
+
+ /* Don't change TXFRAMNUM on usb31 version */
+ size = DWC3_IP_IS(DWC3) ? 0 :
+- dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1)) &
++ dwc3_readl(dwc, DWC3_GTXFIFOSIZ(num >> 1)) &
+ DWC31_GTXFIFOSIZ_TXFRAMNUM;
+
+- dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(num >> 1), size);
++ dwc3_writel(dwc, DWC3_GTXFIFOSIZ(num >> 1), size);
+ dep->flags &= ~DWC3_EP_TXFIFO_RESIZED;
+ }
+ dwc->num_ep_resized = 0;
+@@ -876,7 +876,7 @@ static int dwc3_gadget_resize_tx_fifos(s
+ fifo_size++;
+
+ /* Check if TXFIFOs start at non-zero addr */
+- tmp = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(0));
++ tmp = dwc3_readl(dwc, DWC3_GTXFIFOSIZ(0));
+ fifo_0_start = DWC3_GTXFIFOSIZ_TXFSTADDR(tmp);
+
+ fifo_size |= (fifo_0_start + (dwc->last_fifo_depth << 16));
+@@ -899,7 +899,7 @@ static int dwc3_gadget_resize_tx_fifos(s
+ return -ENOMEM;
+ }
+
+- dwc3_writel(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1), fifo_size);
++ dwc3_writel(dwc, DWC3_GTXFIFOSIZ(dep->number >> 1), fifo_size);
+ dep->flags |= DWC3_EP_TXFIFO_RESIZED;
+ dwc->num_ep_resized++;
+
+@@ -943,9 +943,9 @@ static int __dwc3_gadget_ep_enable(struc
+ dep->type = usb_endpoint_type(desc);
+ dep->flags |= DWC3_EP_ENABLED;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
++ reg = dwc3_readl(dwc, DWC3_DALEPENA);
+ reg |= DWC3_DALEPENA_EP(dep->number);
+- dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
++ dwc3_writel(dwc, DWC3_DALEPENA, reg);
+
+ dep->trb_dequeue = 0;
+ dep->trb_enqueue = 0;
+@@ -1080,9 +1080,9 @@ static int __dwc3_gadget_ep_disable(stru
+ if (dep->flags & DWC3_EP_STALL)
+ __dwc3_gadget_ep_set_halt(dep, 0, false);
+
+- reg = dwc3_readl(dwc->regs, DWC3_DALEPENA);
++ reg = dwc3_readl(dwc, DWC3_DALEPENA);
+ reg &= ~DWC3_DALEPENA_EP(dep->number);
+- dwc3_writel(dwc->regs, DWC3_DALEPENA, reg);
++ dwc3_writel(dwc, DWC3_DALEPENA, reg);
+
+ dwc3_remove_requests(dwc, dep, -ESHUTDOWN);
+
+@@ -1743,7 +1743,7 @@ static int __dwc3_gadget_get_frame(struc
+ {
+ u32 reg;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
++ reg = dwc3_readl(dwc, DWC3_DSTS);
+ return DWC3_DSTS_SOFFN(reg);
+ }
+
+@@ -2351,13 +2351,13 @@ static void dwc3_gadget_enable_linksts_e
+ if (DWC3_VER_IS_PRIOR(DWC3, 250A))
+ return;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DEVTEN);
++ reg = dwc3_readl(dwc, DWC3_DEVTEN);
+ if (set)
+ reg |= DWC3_DEVTEN_ULSTCNGEN;
+ else
+ reg &= ~DWC3_DEVTEN_ULSTCNGEN;
+
+- dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
++ dwc3_writel(dwc, DWC3_DEVTEN, reg);
+ }
+
+ static int dwc3_gadget_get_frame(struct usb_gadget *g)
+@@ -2380,7 +2380,7 @@ static int __dwc3_gadget_wakeup(struct d
+ *
+ * We can check that via USB Link State bits in DSTS register.
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
++ reg = dwc3_readl(dwc, DWC3_DSTS);
+
+ link_state = DWC3_DSTS_USBLNKST(reg);
+
+@@ -2408,9 +2408,9 @@ static int __dwc3_gadget_wakeup(struct d
+ /* Recent versions do this automatically */
+ if (DWC3_VER_IS_PRIOR(DWC3, 194A)) {
+ /* write zeroes to Link Change Request */
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ reg &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
+- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
++ dwc3_writel(dwc, DWC3_DCTL, reg);
+ }
+
+ /*
+@@ -2530,7 +2530,7 @@ static void __dwc3_gadget_set_ssp_rate(s
+ if (ssp_rate == USB_SSP_GEN_UNKNOWN)
+ ssp_rate = dwc->max_ssp_rate;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCFG);
++ reg = dwc3_readl(dwc, DWC3_DCFG);
+ reg &= ~DWC3_DCFG_SPEED_MASK;
+ reg &= ~DWC3_DCFG_NUMLANES(~0);
+
+@@ -2543,7 +2543,7 @@ static void __dwc3_gadget_set_ssp_rate(s
+ dwc->max_ssp_rate != USB_SSP_GEN_2x1)
+ reg |= DWC3_DCFG_NUMLANES(1);
+
+- dwc3_writel(dwc->regs, DWC3_DCFG, reg);
++ dwc3_writel(dwc, DWC3_DCFG, reg);
+ }
+
+ static void __dwc3_gadget_set_speed(struct dwc3 *dwc)
+@@ -2561,7 +2561,7 @@ static void __dwc3_gadget_set_speed(stru
+ return;
+ }
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCFG);
++ reg = dwc3_readl(dwc, DWC3_DCFG);
+ reg &= ~(DWC3_DCFG_SPEED_MASK);
+
+ /*
+@@ -2612,7 +2612,7 @@ static void __dwc3_gadget_set_speed(stru
+ speed < USB_SPEED_SUPER_PLUS)
+ reg &= ~DWC3_DCFG_NUMLANES(~0);
+
+- dwc3_writel(dwc->regs, DWC3_DCFG, reg);
++ dwc3_writel(dwc, DWC3_DCFG, reg);
+ }
+
+ static int dwc3_gadget_run_stop(struct dwc3 *dwc, int is_on)
+@@ -2637,7 +2637,7 @@ static int dwc3_gadget_run_stop(struct d
+ * mentioned in the dwc3 programming guide. It has been tested on an
+ * Exynos platforms.
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0));
+ if (reg & DWC3_GUSB2PHYCFG_SUSPHY) {
+ saved_config |= DWC3_GUSB2PHYCFG_SUSPHY;
+ reg &= ~DWC3_GUSB2PHYCFG_SUSPHY;
+@@ -2649,9 +2649,9 @@ static int dwc3_gadget_run_stop(struct d
+ }
+
+ if (saved_config)
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg);
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ if (is_on) {
+ if (DWC3_VER_IS_WITHIN(DWC3, ANY, 187A)) {
+ reg &= ~DWC3_DCTL_TRGTULST_MASK;
+@@ -2675,14 +2675,14 @@ static int dwc3_gadget_run_stop(struct d
+
+ do {
+ usleep_range(1000, 2000);
+- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
++ reg = dwc3_readl(dwc, DWC3_DSTS);
+ reg &= DWC3_DSTS_DEVCTRLHLT;
+ } while (--timeout && !(!is_on ^ !reg));
+
+ if (saved_config) {
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0));
+ reg |= saved_config;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYCFG(0), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYCFG(0), reg);
+ }
+
+ if (!timeout)
+@@ -2858,13 +2858,13 @@ static void dwc3_gadget_enable_irq(struc
+ if (!DWC3_VER_IS_PRIOR(DWC3, 230A))
+ reg |= DWC3_DEVTEN_U3L2L1SUSPEN;
+
+- dwc3_writel(dwc->regs, DWC3_DEVTEN, reg);
++ dwc3_writel(dwc, DWC3_DEVTEN, reg);
+ }
+
+ static void dwc3_gadget_disable_irq(struct dwc3 *dwc)
+ {
+ /* mask all interrupts */
+- dwc3_writel(dwc->regs, DWC3_DEVTEN, 0x00);
++ dwc3_writel(dwc, DWC3_DEVTEN, 0x00);
+ }
+
+ static irqreturn_t dwc3_interrupt(int irq, void *_dwc);
+@@ -2905,10 +2905,10 @@ static void dwc3_gadget_setup_nump(struc
+ nump = min_t(u32, nump, 16);
+
+ /* update NumP */
+- reg = dwc3_readl(dwc->regs, DWC3_DCFG);
++ reg = dwc3_readl(dwc, DWC3_DCFG);
+ reg &= ~DWC3_DCFG_NUMP_MASK;
+ reg |= nump << DWC3_DCFG_NUMP_SHIFT;
+- dwc3_writel(dwc->regs, DWC3_DCFG, reg);
++ dwc3_writel(dwc, DWC3_DCFG, reg);
+ }
+
+ static int __dwc3_gadget_start(struct dwc3 *dwc)
+@@ -2922,10 +2922,10 @@ static int __dwc3_gadget_start(struct dw
+ * the core supports IMOD, disable it.
+ */
+ if (dwc->imod_interval) {
+- dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), dwc->imod_interval);
+- dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB);
++ dwc3_writel(dwc, DWC3_DEV_IMOD(0), dwc->imod_interval);
++ dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB);
+ } else if (dwc3_has_imod(dwc)) {
+- dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), 0);
++ dwc3_writel(dwc, DWC3_DEV_IMOD(0), 0);
+ }
+
+ /*
+@@ -2935,13 +2935,13 @@ static int __dwc3_gadget_start(struct dw
+ * This way, we maximize the chances that we'll be able to get several
+ * bursts of data without going through any sort of endpoint throttling.
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_GRXTHRCFG);
++ reg = dwc3_readl(dwc, DWC3_GRXTHRCFG);
+ if (DWC3_IP_IS(DWC3))
+ reg &= ~DWC3_GRXTHRCFG_PKTCNTSEL;
+ else
+ reg &= ~DWC31_GRXTHRCFG_PKTCNTSEL;
+
+- dwc3_writel(dwc->regs, DWC3_GRXTHRCFG, reg);
++ dwc3_writel(dwc, DWC3_GRXTHRCFG, reg);
+
+ dwc3_gadget_setup_nump(dwc);
+
+@@ -2952,15 +2952,15 @@ static int __dwc3_gadget_start(struct dw
+ * ACK with NumP=0 and PP=0 (for IN direction). This slightly improves
+ * the stream performance.
+ */
+- reg = dwc3_readl(dwc->regs, DWC3_DCFG);
++ reg = dwc3_readl(dwc, DWC3_DCFG);
+ reg |= DWC3_DCFG_IGNSTRMPP;
+- dwc3_writel(dwc->regs, DWC3_DCFG, reg);
++ dwc3_writel(dwc, DWC3_DCFG, reg);
+
+ /* Enable MST by default if the device is capable of MST */
+ if (DWC3_MST_CAPABLE(&dwc->hwparams)) {
+- reg = dwc3_readl(dwc->regs, DWC3_DCFG1);
++ reg = dwc3_readl(dwc, DWC3_DCFG1);
+ reg &= ~DWC3_DCFG1_DIS_MST_ENH;
+- dwc3_writel(dwc->regs, DWC3_DCFG1, reg);
++ dwc3_writel(dwc, DWC3_DCFG1, reg);
+ }
+
+ /* Start with SuperSpeed Default */
+@@ -3238,7 +3238,7 @@ static int dwc3_gadget_init_in_endpoint(
+ /* MDWIDTH is represented in bits, we need it in bytes */
+ mdwidth /= 8;
+
+- size = dwc3_readl(dwc->regs, DWC3_GTXFIFOSIZ(dep->number >> 1));
++ size = dwc3_readl(dwc, DWC3_GTXFIFOSIZ(dep->number >> 1));
+ if (DWC3_IP_IS(DWC3))
+ size = DWC3_GTXFIFOSIZ_TXFDEP(size);
+ else
+@@ -3287,7 +3287,7 @@ static int dwc3_gadget_init_out_endpoint
+ mdwidth /= 8;
+
+ /* All OUT endpoints share a single RxFIFO space */
+- size = dwc3_readl(dwc->regs, DWC3_GRXFIFOSIZ(0));
++ size = dwc3_readl(dwc, DWC3_GRXFIFOSIZ(0));
+ if (DWC3_IP_IS(DWC3))
+ size = DWC3_GRXFIFOSIZ_RXFDEP(size);
+ else
+@@ -3740,9 +3740,9 @@ out:
+ return no_started_trb;
+ }
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ reg |= dwc->u1u2;
+- dwc3_writel(dwc->regs, DWC3_DCTL, reg);
++ dwc3_writel(dwc, DWC3_DCTL, reg);
+
+ dwc->u1u2 = 0;
+ }
+@@ -4072,7 +4072,7 @@ static void dwc3_gadget_disconnect_inter
+
+ dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RX_DET);
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ reg &= ~DWC3_DCTL_INITU1ENA;
+ reg &= ~DWC3_DCTL_INITU2ENA;
+ dwc3_gadget_dctl_write_safe(dwc, reg);
+@@ -4161,7 +4161,7 @@ static void dwc3_gadget_reset_interrupt(
+ dwc3_stop_active_transfers(dwc);
+ dwc->connected = true;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ reg &= ~DWC3_DCTL_TSTCTRL_MASK;
+ dwc3_gadget_dctl_write_safe(dwc, reg);
+ dwc->test_mode = false;
+@@ -4170,9 +4170,9 @@ static void dwc3_gadget_reset_interrupt(
+ dwc3_clear_stall_all_ep(dwc);
+
+ /* Reset device address to zero */
+- reg = dwc3_readl(dwc->regs, DWC3_DCFG);
++ reg = dwc3_readl(dwc, DWC3_DCFG);
+ reg &= ~(DWC3_DCFG_DEVADDR_MASK);
+- dwc3_writel(dwc->regs, DWC3_DCFG, reg);
++ dwc3_writel(dwc, DWC3_DCFG, reg);
+ }
+
+ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
+@@ -4186,7 +4186,7 @@ static void dwc3_gadget_conndone_interru
+ if (!dwc->softconnect)
+ return;
+
+- reg = dwc3_readl(dwc->regs, DWC3_DSTS);
++ reg = dwc3_readl(dwc, DWC3_DSTS);
+ speed = reg & DWC3_DSTS_CONNECTSPD;
+ dwc->speed = speed;
+
+@@ -4261,11 +4261,11 @@ static void dwc3_gadget_conndone_interru
+ !dwc->usb2_gadget_lpm_disable &&
+ (speed != DWC3_DSTS_SUPERSPEED) &&
+ (speed != DWC3_DSTS_SUPERSPEED_PLUS)) {
+- reg = dwc3_readl(dwc->regs, DWC3_DCFG);
++ reg = dwc3_readl(dwc, DWC3_DCFG);
+ reg |= DWC3_DCFG_LPM_CAP;
+- dwc3_writel(dwc->regs, DWC3_DCFG, reg);
++ dwc3_writel(dwc, DWC3_DCFG, reg);
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ reg &= ~(DWC3_DCTL_HIRD_THRES_MASK | DWC3_DCTL_L1_HIBER_EN);
+
+ reg |= DWC3_DCTL_HIRD_THRES(dwc->hird_threshold |
+@@ -4288,12 +4288,12 @@ static void dwc3_gadget_conndone_interru
+ dwc3_gadget_dctl_write_safe(dwc, reg);
+ } else {
+ if (dwc->usb2_gadget_lpm_disable) {
+- reg = dwc3_readl(dwc->regs, DWC3_DCFG);
++ reg = dwc3_readl(dwc, DWC3_DCFG);
+ reg &= ~DWC3_DCFG_LPM_CAP;
+- dwc3_writel(dwc->regs, DWC3_DCFG, reg);
++ dwc3_writel(dwc, DWC3_DCFG, reg);
+ }
+
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ reg &= ~DWC3_DCTL_HIRD_THRES_MASK;
+ dwc3_gadget_dctl_write_safe(dwc, reg);
+ }
+@@ -4399,7 +4399,7 @@ static void dwc3_gadget_linksts_change_i
+ switch (dwc->link_state) {
+ case DWC3_LINK_STATE_U1:
+ case DWC3_LINK_STATE_U2:
+- reg = dwc3_readl(dwc->regs, DWC3_DCTL);
++ reg = dwc3_readl(dwc, DWC3_DCTL);
+ u1u2 = reg & (DWC3_DCTL_INITU2ENA
+ | DWC3_DCTL_ACCEPTU2ENA
+ | DWC3_DCTL_INITU1ENA
+@@ -4556,7 +4556,7 @@ static irqreturn_t dwc3_process_event_bu
+ ret = IRQ_HANDLED;
+
+ /* Unmask interrupt */
+- dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
++ dwc3_writel(dwc, DWC3_GEVNTSIZ(0),
+ DWC3_GEVNTSIZ_SIZE(evt->length));
+
+ evt->flags &= ~DWC3_EVENT_PENDING;
+@@ -4567,8 +4567,8 @@ static irqreturn_t dwc3_process_event_bu
+ wmb();
+
+ if (dwc->imod_interval) {
+- dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB);
+- dwc3_writel(dwc->regs, DWC3_DEV_IMOD(0), dwc->imod_interval);
++ dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), DWC3_GEVNTCOUNT_EHB);
++ dwc3_writel(dwc, DWC3_DEV_IMOD(0), dwc->imod_interval);
+ }
+
+ return ret;
+@@ -4617,7 +4617,7 @@ static irqreturn_t dwc3_check_event_buf(
+ if (evt->flags & DWC3_EVENT_PENDING)
+ return IRQ_HANDLED;
+
+- count = dwc3_readl(dwc->regs, DWC3_GEVNTCOUNT(0));
++ count = dwc3_readl(dwc, DWC3_GEVNTCOUNT(0));
+ count &= DWC3_GEVNTCOUNT_MASK;
+ if (!count)
+ return IRQ_NONE;
+@@ -4632,7 +4632,7 @@ static irqreturn_t dwc3_check_event_buf(
+ evt->flags |= DWC3_EVENT_PENDING;
+
+ /* Mask interrupt */
+- dwc3_writel(dwc->regs, DWC3_GEVNTSIZ(0),
++ dwc3_writel(dwc, DWC3_GEVNTSIZ(0),
+ DWC3_GEVNTSIZ_INTMASK | DWC3_GEVNTSIZ_SIZE(evt->length));
+
+ amount = min(count, evt->length - evt->lpos);
+@@ -4641,7 +4641,7 @@ static irqreturn_t dwc3_check_event_buf(
+ if (amount < count)
+ memcpy(evt->cache, evt->buf, count - amount);
+
+- dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), count);
++ dwc3_writel(dwc, DWC3_GEVNTCOUNT(0), count);
+
+ return IRQ_WAKE_THREAD;
+ }
+--- a/drivers/usb/dwc3/gadget.h
++++ b/drivers/usb/dwc3/gadget.h
+@@ -132,7 +132,7 @@ static inline void dwc3_gadget_ep_get_tr
+ {
+ u32 res_id;
+
+- res_id = dwc3_readl(dep->dwc->regs, DWC3_DEPCMD(dep->number));
++ res_id = dwc3_readl(dep->dwc, DWC3_DEPCMD(dep->number));
+ dep->resource_index = DWC3_DEPCMD_GET_RSC_IDX(res_id);
+ }
+
+@@ -147,7 +147,7 @@ static inline void dwc3_gadget_ep_get_tr
+ static inline void dwc3_gadget_dctl_write_safe(struct dwc3 *dwc, u32 value)
+ {
+ value &= ~DWC3_DCTL_ULSTCHNGREQ_MASK;
+- dwc3_writel(dwc->regs, DWC3_DCTL, value);
++ dwc3_writel(dwc, DWC3_DCTL, value);
+ }
+
+ #endif /* __DRIVERS_USB_DWC3_GADGET_H */
+--- a/drivers/usb/dwc3/io.h
++++ b/drivers/usb/dwc3/io.h
+@@ -16,9 +16,10 @@
+ #include "debug.h"
+ #include "core.h"
+
+-static inline u32 dwc3_readl(void __iomem *base, u32 offset)
++static inline u32 dwc3_readl(struct dwc3 *dwc, u32 offset)
+ {
+ u32 value;
++ void __iomem *base = dwc->regs;
+
+ /*
+ * We requested the mem region starting from the Globals address
+@@ -37,8 +38,10 @@ static inline u32 dwc3_readl(void __iome
+ return value;
+ }
+
+-static inline void dwc3_writel(void __iomem *base, u32 offset, u32 value)
++static inline void dwc3_writel(struct dwc3 *dwc, u32 offset, u32 value)
+ {
++ void __iomem *base = dwc->regs;
++
+ /*
+ * We requested the mem region starting from the Globals address
+ * space, see dwc3_probe in core.c.
+--- a/drivers/usb/dwc3/ulpi.c
++++ b/drivers/usb/dwc3/ulpi.c
+@@ -33,13 +33,13 @@ static int dwc3_ulpi_busyloop(struct dwc
+ if (read)
+ ns += DWC3_ULPI_BASE_DELAY;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYCFG(0));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYCFG(0));
+ if (reg & DWC3_GUSB2PHYCFG_SUSPHY)
+ usleep_range(1000, 1200);
+
+ while (count--) {
+ ndelay(ns);
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYACC(0));
+ if (reg & DWC3_GUSB2PHYACC_DONE)
+ return 0;
+ cpu_relax();
+@@ -55,13 +55,13 @@ static int dwc3_ulpi_read(struct device
+ int ret;
+
+ reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYACC(0), reg);
+
+ ret = dwc3_ulpi_busyloop(dwc, addr, true);
+ if (ret)
+ return ret;
+
+- reg = dwc3_readl(dwc->regs, DWC3_GUSB2PHYACC(0));
++ reg = dwc3_readl(dwc, DWC3_GUSB2PHYACC(0));
+
+ return DWC3_GUSB2PHYACC_DATA(reg);
+ }
+@@ -73,7 +73,7 @@ static int dwc3_ulpi_write(struct device
+
+ reg = DWC3_GUSB2PHYACC_NEWREGREQ | DWC3_ULPI_ADDR(addr);
+ reg |= DWC3_GUSB2PHYACC_WRITE | val;
+- dwc3_writel(dwc->regs, DWC3_GUSB2PHYACC(0), reg);
++ dwc3_writel(dwc, DWC3_GUSB2PHYACC(0), reg);
+
+ return dwc3_ulpi_busyloop(dwc, addr, false);
+ }
--- /dev/null
+From stable+bounces-246815-greg=kroah.com@vger.kernel.org Wed May 13 13:27:53 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 07:27:44 -0400
+Subject: usb: dwc3: Move GUID programming after PHY initialization
+To: stable@vger.kernel.org
+Cc: Selvarasu Ganesan <selvarasu.g@samsung.com>, stable <stable@kernel.org>, Pritam Manohar Sutar <pritam.sutar@samsung.com>, Thinh Nguyen <Thinh.Nguyen@synopsys.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513112744.3646168-3-sashal@kernel.org>
+
+From: Selvarasu Ganesan <selvarasu.g@samsung.com>
+
+[ Upstream commit aad35f9c926ec220b0742af1ada45666ae667956 ]
+
+The Linux Version Code is currently written to the GUID register before
+PHY initialization. Certain PHY implementations (such as Synopsys eUSB
+PHY performing link_sw_reset) clear the GUID register to its default
+value during initialization, causing the kernel version information to
+be lost.
+
+Move the GUID register programming to occur after PHY initialization
+completes to ensure the Linux version information persists.
+
+Fixes: fa0ea13e9f1c ("usb: dwc3: core: write LINUX_VERSION_CODE to our GUID register")
+Cc: stable <stable@kernel.org>
+Reported-by: Pritam Manohar Sutar <pritam.sutar@samsung.com>
+Signed-off-by: Selvarasu Ganesan <selvarasu.g@samsung.com>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://patch.msgid.link/20260417063314.2359-1-selvarasu.g@samsung.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/core.c | 12 ++++++------
+ 1 file changed, 6 insertions(+), 6 deletions(-)
+
+--- a/drivers/usb/dwc3/core.c
++++ b/drivers/usb/dwc3/core.c
+@@ -1339,12 +1339,6 @@ static int dwc3_core_init(struct dwc3 *d
+
+ hw_mode = DWC3_GHWPARAMS0_MODE(dwc->hwparams.hwparams0);
+
+- /*
+- * Write Linux Version Code to our GUID register so it's easy to figure
+- * out which kernel version a bug was found.
+- */
+- dwc3_writel(dwc, DWC3_GUID, LINUX_VERSION_CODE);
+-
+ ret = dwc3_phy_setup(dwc);
+ if (ret)
+ return ret;
+@@ -1376,6 +1370,12 @@ static int dwc3_core_init(struct dwc3 *d
+ if (ret)
+ goto err_exit_phy;
+
++ /*
++ * Write Linux Version Code to our GUID register so it's easy to figure
++ * out which kernel version a bug was found.
++ */
++ dwc3_writel(dwc, DWC3_GUID, LINUX_VERSION_CODE);
++
+ dwc3_core_setup_global_control(dwc);
+ dwc3_core_num_eps(dwc);
+
--- /dev/null
+From sashal@kernel.org Wed May 13 13:27:48 2026
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 13 May 2026 07:27:42 -0400
+Subject: usb: dwc3: Remove of dep->regs
+To: stable@vger.kernel.org
+Cc: Prashanth K <prashanth.k@oss.qualcomm.com>, Thinh Nguyen <Thinh.Nguyen@synopsys.com>, Greg Kroah-Hartman <gregkh@linuxfoundation.org>, Sasha Levin <sashal@kernel.org>
+Message-ID: <20260513112744.3646168-1-sashal@kernel.org>
+
+From: Prashanth K <prashanth.k@oss.qualcomm.com>
+
+[ Upstream commit abdd1eef04f0cb3b1707cd1fa243d574d5e07024 ]
+
+Remove dep->regs from struct dwc3_ep and reuse dwc->regs instead.
+Thus eliminating redundant iomem addresses and making register
+access more consistent across the driver.
+
+Signed-off-by: Prashanth K <prashanth.k@oss.qualcomm.com>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Link: https://patch.msgid.link/20260114100748.2950103-2-prashanth.k@oss.qualcomm.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: aad35f9c926e ("usb: dwc3: Move GUID programming after PHY initialization")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/dwc3/core.h | 10 ++++------
+ drivers/usb/dwc3/debugfs.c | 12 ++++--------
+ drivers/usb/dwc3/gadget.c | 12 ++++++------
+ drivers/usb/dwc3/gadget.h | 2 +-
+ 4 files changed, 15 insertions(+), 21 deletions(-)
+
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -165,10 +165,10 @@
+ #define DWC3_DCFG1 0xc740 /* DWC_usb32 only */
+
+ #define DWC3_DEP_BASE(n) (0xc800 + ((n) * 0x10))
+-#define DWC3_DEPCMDPAR2 0x00
+-#define DWC3_DEPCMDPAR1 0x04
+-#define DWC3_DEPCMDPAR0 0x08
+-#define DWC3_DEPCMD 0x0c
++#define DWC3_DEPCMDPAR2(n) (DWC3_DEP_BASE(n) + 0x00)
++#define DWC3_DEPCMDPAR1(n) (DWC3_DEP_BASE(n) + 0x04)
++#define DWC3_DEPCMDPAR0(n) (DWC3_DEP_BASE(n) + 0x08)
++#define DWC3_DEPCMD(n) (DWC3_DEP_BASE(n) + 0x0c)
+
+ #define DWC3_DEV_IMOD(n) (0xca00 + ((n) * 0x4))
+
+@@ -749,8 +749,6 @@ struct dwc3_ep {
+ struct list_head pending_list;
+ struct list_head started_list;
+
+- void __iomem *regs;
+-
+ struct dwc3_trb *trb_pool;
+ dma_addr_t trb_pool_dma;
+ struct dwc3 *dwc;
+--- a/drivers/usb/dwc3/debugfs.c
++++ b/drivers/usb/dwc3/debugfs.c
+@@ -36,23 +36,19 @@
+ #define dump_ep_register_set(n) \
+ { \
+ .name = "DEPCMDPAR2("__stringify(n)")", \
+- .offset = DWC3_DEP_BASE(n) + \
+- DWC3_DEPCMDPAR2, \
++ .offset = DWC3_DEPCMDPAR2(n), \
+ }, \
+ { \
+ .name = "DEPCMDPAR1("__stringify(n)")", \
+- .offset = DWC3_DEP_BASE(n) + \
+- DWC3_DEPCMDPAR1, \
++ .offset = DWC3_DEPCMDPAR1(n), \
+ }, \
+ { \
+ .name = "DEPCMDPAR0("__stringify(n)")", \
+- .offset = DWC3_DEP_BASE(n) + \
+- DWC3_DEPCMDPAR0, \
++ .offset = DWC3_DEPCMDPAR0(n), \
+ }, \
+ { \
+ .name = "DEPCMD("__stringify(n)")", \
+- .offset = DWC3_DEP_BASE(n) + \
+- DWC3_DEPCMD, \
++ .offset = DWC3_DEPCMD(n), \
+ }
+
+
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -320,6 +320,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_
+
+ int cmd_status = 0;
+ int ret = -EINVAL;
++ u8 epnum = dep->number;
+
+ /*
+ * When operating in USB 2.0 speeds (HS/FS), if GUSB2PHYCFG.ENBLSLPM or
+@@ -355,9 +356,9 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_
+ * improve performance.
+ */
+ if (DWC3_DEPCMD_CMD(cmd) != DWC3_DEPCMD_UPDATETRANSFER) {
+- dwc3_writel(dep->regs, DWC3_DEPCMDPAR0, params->param0);
+- dwc3_writel(dep->regs, DWC3_DEPCMDPAR1, params->param1);
+- dwc3_writel(dep->regs, DWC3_DEPCMDPAR2, params->param2);
++ dwc3_writel(dwc->regs, DWC3_DEPCMDPAR0(epnum), params->param0);
++ dwc3_writel(dwc->regs, DWC3_DEPCMDPAR1(epnum), params->param1);
++ dwc3_writel(dwc->regs, DWC3_DEPCMDPAR2(epnum), params->param2);
+ }
+
+ /*
+@@ -381,7 +382,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_
+ else
+ cmd |= DWC3_DEPCMD_CMDACT;
+
+- dwc3_writel(dep->regs, DWC3_DEPCMD, cmd);
++ dwc3_writel(dwc->regs, DWC3_DEPCMD(epnum), cmd);
+
+ if (!(cmd & DWC3_DEPCMD_CMDACT) ||
+ (DWC3_DEPCMD_CMD(cmd) == DWC3_DEPCMD_ENDTRANSFER &&
+@@ -391,7 +392,7 @@ int dwc3_send_gadget_ep_cmd(struct dwc3_
+ }
+
+ do {
+- reg = dwc3_readl(dep->regs, DWC3_DEPCMD);
++ reg = dwc3_readl(dwc->regs, DWC3_DEPCMD(epnum));
+ if (!(reg & DWC3_DEPCMD_CMDACT)) {
+ cmd_status = DWC3_DEPCMD_STATUS(reg);
+
+@@ -3379,7 +3380,6 @@ static int dwc3_gadget_init_endpoint(str
+ dep->dwc = dwc;
+ dep->number = epnum;
+ dep->direction = direction;
+- dep->regs = dwc->regs + DWC3_DEP_BASE(epnum);
+ dwc->eps[epnum] = dep;
+ dep->combo_num = 0;
+ dep->start_cmd_status = 0;
+--- a/drivers/usb/dwc3/gadget.h
++++ b/drivers/usb/dwc3/gadget.h
+@@ -132,7 +132,7 @@ static inline void dwc3_gadget_ep_get_tr
+ {
+ u32 res_id;
+
+- res_id = dwc3_readl(dep->regs, DWC3_DEPCMD);
++ res_id = dwc3_readl(dep->dwc->regs, DWC3_DEPCMD(dep->number));
+ dep->resource_index = DWC3_DEPCMD_GET_RSC_IDX(res_id);
+ }
+
--- /dev/null
+From 2909f0d4994fb4306bf116df5ccee797791fce2c Mon Sep 17 00:00:00 2001
+From: Amit Sunil Dhamne <amitsd@google.com>
+Date: Tue, 14 Apr 2026 00:58:32 +0000
+Subject: usb: typec: tcpm: reset internal port states on soft reset AMS
+
+From: Amit Sunil Dhamne <amitsd@google.com>
+
+commit 2909f0d4994fb4306bf116df5ccee797791fce2c upstream.
+
+Reset internal port states (such as vdm_sm_running and
+explicit_contract) on soft reset AMS as the port needs to negotiate a
+new contract. The consequence of leaving the states in as-is cond are as
+follows:
+ * port is in SRC power role and an explicit contract is negotiated
+ with the port partner (in sink role)
+ * port partner sends a Soft Reset AMS while VDM State Machine is
+ running
+ * port accepts the Soft Reset request and the port advertises src caps
+ * port partner sends a Request message but since the explicit_contract
+ and vdm_sm_running are true from previous negotiation, the port ends
+ up sending Soft Reset instead of Accept msg.
+
+Stub Log:
+[ 203.653942] AMS DISCOVER_IDENTITY start
+[ 203.653947] PD TX, header: 0x176f
+[ 203.655901] PD TX complete, status: 0
+[ 203.657470] PD RX, header: 0x124f [1]
+[ 203.657477] Rx VDM cmd 0xff008081 type 2 cmd 1 len 1
+[ 203.657482] AMS DISCOVER_IDENTITY finished
+[ 203.657484] cc:=4
+[ 204.155698] PD RX, header: 0x144f [1]
+[ 204.155718] Rx VDM cmd 0xeeee8001 type 0 cmd 1 len 1
+[ 204.155741] PD TX, header: 0x196f
+[ 204.157622] PD TX complete, status: 0
+[ 204.160060] PD RX, header: 0x4d [1]
+[ 204.160066] state change SRC_READY -> SOFT_RESET [rev2 SOFT_RESET_AMS]
+[ 204.160076] PD TX, header: 0x163
+[ 204.162486] PD TX complete, status: 0
+[ 204.162832] AMS SOFT_RESET_AMS finished
+[ 204.162840] cc:=4
+[ 204.162891] AMS POWER_NEGOTIATION start
+[ 204.162896] state change SOFT_RESET -> AMS_START [rev2 POWER_NEGOTIATION]
+[ 204.162908] state change AMS_START -> SRC_SEND_CAPABILITIES [rev2 POWER_NEGOTIATION]
+[ 204.162913] PD TX, header: 0x1361
+[ 204.165529] PD TX complete, status: 0
+[ 204.165571] pending state change SRC_SEND_CAPABILITIES -> SRC_SEND_CAPABILITIES_TIMEOUT @ 60 ms [rev2 POWER_NEGOTIATION]
+[ 204.166996] PD RX, header: 0x1242 [1]
+[ 204.167009] state change SRC_SEND_CAPABILITIES -> SRC_SOFT_RESET_WAIT_SNK_TX [rev2 POWER_NEGOTIATION]
+[ 204.167019] AMS POWER_NEGOTIATION finished
+[ 204.167020] cc:=4
+[ 204.167083] AMS SOFT_RESET_AMS start
+[ 204.167086] state change SRC_SOFT_RESET_WAIT_SNK_TX -> SOFT_RESET_SEND [rev2 SOFT_RESET_AMS]
+[ 204.167092] PD TX, header: 0x16d
+[ 204.168824] PD TX complete, status: 0
+[ 204.168854] pending state change SOFT_RESET_SEND -> HARD_RESET_SEND @ 60 ms [rev2 SOFT_RESET_AMS]
+[ 204.171876] PD RX, header: 0x43 [1]
+[ 204.171879] AMS SOFT_RESET_AMS finished
+
+This causes COMMON.PROC.PD.11.2 check failure for
+TEST.PD.VDM.SRC.2_Rev2Src test on the PD compliance tester.
+
+Signed-off-by: Amit Sunil Dhamne <amitsd@google.com>
+Fixes: 8d3a0578ad1a ("usb: typec: tcpm: Respond Wait if VDM state machine is running")
+Fixes: f0690a25a140 ("staging: typec: USB Type-C Port Manager (tcpm)")
+Cc: stable <stable@kernel.org>
+Reviewed-by: Badhri Jagan Sridharan <badhri@google.com>
+Acked-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
+Link: https://patch.msgid.link/20260414-fix-soft-reset-v1-1-01d7cb9764e2@google.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/usb/typec/tcpm/tcpm.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+--- a/drivers/usb/typec/tcpm/tcpm.c
++++ b/drivers/usb/typec/tcpm/tcpm.c
+@@ -5526,6 +5526,8 @@ static void run_state_machine(struct tcp
+ usb_power_delivery_unregister_capabilities(port->partner_source_caps);
+ port->partner_source_caps = NULL;
+ tcpm_pd_send_control(port, PD_CTRL_ACCEPT, TCPC_TX_SOP);
++ port->vdm_sm_running = false;
++ port->explicit_contract = false;
+ tcpm_ams_finish(port);
+ if (port->pwr_role == TYPEC_SOURCE) {
+ port->upcoming_state = SRC_SEND_CAPABILITIES;