]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 May 2026 09:30:20 +0000 (11:30 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 15 May 2026 09:30:20 +0000 (11:30 +0200)
added patches:
block-fix-zone-write-plug-removal.patch
bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch
drm-amdgpu-fix-validating-flush_gpu_tlb_pasid.patch
drm-amdgpu-rework-how-we-handle-tlb-fences.patch
drm-amdgpu-validate-the-flush_gpu_tlb_pasid.patch
edac-versalnet-fix-device-name-memory-leak.patch
fbcon-avoid-oob-font-access-if-console-rotation-fails.patch
fbcon-rename-struct-fbcon_ops-to-struct-fbcon_par.patch
loongarch-kvm-compile-switch.s-directly-into-the-kernel.patch
mm-damon-core-disallow-time-quota-setting-zero-esz.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
papr-hvpipe-convert-papr_hvpipe_dev_create_handle-to-fd_prepare.patch
pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch
revert-drm-amdgpu-don-t-attach-the-tlb-fence-for-si.patch
sched-ext-implement-cgroup_set_idle-callback.patch
sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch
spi-tegra114-fix-controller-deregistration.patch
spi-tegra20-sflash-fix-controller-deregistration.patch
spi-uniphier-fix-controller-deregistration.patch
spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch
spi-zynq-qspi-fix-controller-deregistration.patch
spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch
usb-dwc3-add-dwc-pointer-to-dwc3_readl-writel.patch
usb-dwc3-move-guid-programming-after-phy-initialization.patch
usb-dwc3-remove-of-dep-regs.patch
usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch

29 files changed:
queue-6.18/block-fix-zone-write-plug-removal.patch [new file with mode: 0644]
queue-6.18/bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch [new file with mode: 0644]
queue-6.18/drm-amdgpu-fix-validating-flush_gpu_tlb_pasid.patch [new file with mode: 0644]
queue-6.18/drm-amdgpu-rework-how-we-handle-tlb-fences.patch [new file with mode: 0644]
queue-6.18/drm-amdgpu-validate-the-flush_gpu_tlb_pasid.patch [new file with mode: 0644]
queue-6.18/edac-versalnet-fix-device-name-memory-leak.patch [new file with mode: 0644]
queue-6.18/fbcon-avoid-oob-font-access-if-console-rotation-fails.patch [new file with mode: 0644]
queue-6.18/fbcon-rename-struct-fbcon_ops-to-struct-fbcon_par.patch [new file with mode: 0644]
queue-6.18/loongarch-kvm-compile-switch.s-directly-into-the-kernel.patch [new file with mode: 0644]
queue-6.18/mm-damon-core-disallow-time-quota-setting-zero-esz.patch [new file with mode: 0644]
queue-6.18/mm-damon-core-implement-damon_kdamond_pid.patch [new file with mode: 0644]
queue-6.18/mm-damon-lru_sort-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch [new file with mode: 0644]
queue-6.18/mm-damon-reclaim-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch [new file with mode: 0644]
queue-6.18/papr-hvpipe-convert-papr_hvpipe_dev_create_handle-to-fd_prepare.patch [new file with mode: 0644]
queue-6.18/pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch [new file with mode: 0644]
queue-6.18/revert-drm-amdgpu-don-t-attach-the-tlb-fence-for-si.patch [new file with mode: 0644]
queue-6.18/sched-ext-implement-cgroup_set_idle-callback.patch [new file with mode: 0644]
queue-6.18/sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch [new file with mode: 0644]
queue-6.18/series
queue-6.18/spi-tegra114-fix-controller-deregistration.patch [new file with mode: 0644]
queue-6.18/spi-tegra20-sflash-fix-controller-deregistration.patch [new file with mode: 0644]
queue-6.18/spi-uniphier-fix-controller-deregistration.patch [new file with mode: 0644]
queue-6.18/spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch [new file with mode: 0644]
queue-6.18/spi-zynq-qspi-fix-controller-deregistration.patch [new file with mode: 0644]
queue-6.18/spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch [new file with mode: 0644]
queue-6.18/usb-dwc3-add-dwc-pointer-to-dwc3_readl-writel.patch [new file with mode: 0644]
queue-6.18/usb-dwc3-move-guid-programming-after-phy-initialization.patch [new file with mode: 0644]
queue-6.18/usb-dwc3-remove-of-dep-regs.patch [new file with mode: 0644]
queue-6.18/usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch [new file with mode: 0644]

diff --git a/queue-6.18/block-fix-zone-write-plug-removal.patch b/queue-6.18/block-fix-zone-write-plug-removal.patch
new file mode 100644 (file)
index 0000000..4e88f8d
--- /dev/null
@@ -0,0 +1,294 @@
+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);
+               }
+       }
diff --git a/queue-6.18/bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch b/queue-6.18/bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch
new file mode 100644 (file)
index 0000000..684fc93
--- /dev/null
@@ -0,0 +1,96 @@
+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);
+       }
diff --git a/queue-6.18/drm-amdgpu-fix-validating-flush_gpu_tlb_pasid.patch b/queue-6.18/drm-amdgpu-fix-validating-flush_gpu_tlb_pasid.patch
new file mode 100644 (file)
index 0000000..8645b25
--- /dev/null
@@ -0,0 +1,47 @@
+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,
diff --git a/queue-6.18/drm-amdgpu-rework-how-we-handle-tlb-fences.patch b/queue-6.18/drm-amdgpu-rework-how-we-handle-tlb-fences.patch
new file mode 100644 (file)
index 0000000..8c8b103
--- /dev/null
@@ -0,0 +1,75 @@
+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;
diff --git a/queue-6.18/drm-amdgpu-validate-the-flush_gpu_tlb_pasid.patch b/queue-6.18/drm-amdgpu-validate-the-flush_gpu_tlb_pasid.patch
new file mode 100644 (file)
index 0000000..d1829be
--- /dev/null
@@ -0,0 +1,35 @@
+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,
diff --git a/queue-6.18/edac-versalnet-fix-device-name-memory-leak.patch b/queue-6.18/edac-versalnet-fix-device-name-memory-leak.patch
new file mode 100644 (file)
index 0000000..d2180f3
--- /dev/null
@@ -0,0 +1,52 @@
+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);
diff --git a/queue-6.18/fbcon-avoid-oob-font-access-if-console-rotation-fails.patch b/queue-6.18/fbcon-avoid-oob-font-access-if-console-rotation-fails.patch
new file mode 100644 (file)
index 0000000..fc6675d
--- /dev/null
@@ -0,0 +1,55 @@
+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;
+       }
diff --git a/queue-6.18/fbcon-rename-struct-fbcon_ops-to-struct-fbcon_par.patch b/queue-6.18/fbcon-rename-struct-fbcon_ops-to-struct-fbcon_par.patch
new file mode 100644 (file)
index 0000000..27b2030
--- /dev/null
@@ -0,0 +1,2459 @@
+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);
+       }
+ }
diff --git a/queue-6.18/loongarch-kvm-compile-switch.s-directly-into-the-kernel.patch b/queue-6.18/loongarch-kvm-compile-switch.s-directly-into-the-kernel.patch
new file mode 100644 (file)
index 0000000..f13de81
--- /dev/null
@@ -0,0 +1,264 @@
+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
diff --git a/queue-6.18/mm-damon-core-disallow-time-quota-setting-zero-esz.patch b/queue-6.18/mm-damon-core-disallow-time-quota-setting-zero-esz.patch
new file mode 100644 (file)
index 0000000..1eb2fea
--- /dev/null
@@ -0,0 +1,88 @@
+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);
+       }
diff --git a/queue-6.18/mm-damon-core-implement-damon_kdamond_pid.patch b/queue-6.18/mm-damon-core-implement-damon_kdamond_pid.patch
new file mode 100644 (file)
index 0000000..8ff8b7c
--- /dev/null
@@ -0,0 +1,86 @@
+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.
diff --git a/queue-6.18/mm-damon-lru_sort-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch b/queue-6.18/mm-damon-lru_sort-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch
new file mode 100644 (file)
index 0000000..3e15d13
--- /dev/null
@@ -0,0 +1,220 @@
+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;
diff --git a/queue-6.18/mm-damon-reclaim-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch b/queue-6.18/mm-damon-reclaim-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch
new file mode 100644 (file)
index 0000000..09290e2
--- /dev/null
@@ -0,0 +1,241 @@
+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;
diff --git a/queue-6.18/papr-hvpipe-convert-papr_hvpipe_dev_create_handle-to-fd_prepare.patch b/queue-6.18/papr-hvpipe-convert-papr_hvpipe_dev_create_handle-to-fd_prepare.patch
new file mode 100644 (file)
index 0000000..e5de4f8
--- /dev/null
@@ -0,0 +1,89 @@
+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);
+ }
+ /*
diff --git a/queue-6.18/pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch b/queue-6.18/pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch
new file mode 100644 (file)
index 0000000..eec3918
--- /dev/null
@@ -0,0 +1,107 @@
+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);
+ }
diff --git a/queue-6.18/revert-drm-amdgpu-don-t-attach-the-tlb-fence-for-si.patch b/queue-6.18/revert-drm-amdgpu-don-t-attach-the-tlb-fence-for-si.patch
new file mode 100644 (file)
index 0000000..ecd74ff
--- /dev/null
@@ -0,0 +1,42 @@
+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 */
diff --git a/queue-6.18/sched-ext-implement-cgroup_set_idle-callback.patch b/queue-6.18/sched-ext-implement-cgroup_set_idle-callback.patch
new file mode 100644 (file)
index 0000000..a6e59a5
--- /dev/null
@@ -0,0 +1,120 @@
+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 */
+       /*
diff --git a/queue-6.18/sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch b/queue-6.18/sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch
new file mode 100644 (file)
index 0000000..6bf1aed
--- /dev/null
@@ -0,0 +1,72 @@
+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 ||
index 876fb5a108280d876949edc774f6798cbf6467a4..10827662072f40a4bcde5be31d466247e2b17c0e 100644 (file)
@@ -144,3 +144,31 @@ batman-adv-bla-put-backbone-reference-on-failed-claim-hash-insert.patch
 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
diff --git a/queue-6.18/spi-tegra114-fix-controller-deregistration.patch b/queue-6.18/spi-tegra114-fix-controller-deregistration.patch
new file mode 100644 (file)
index 0000000..1fa0c6a
--- /dev/null
@@ -0,0 +1,59 @@
+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
diff --git a/queue-6.18/spi-tegra20-sflash-fix-controller-deregistration.patch b/queue-6.18/spi-tegra20-sflash-fix-controller-deregistration.patch
new file mode 100644 (file)
index 0000000..9a2a895
--- /dev/null
@@ -0,0 +1,57 @@
+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
diff --git a/queue-6.18/spi-uniphier-fix-controller-deregistration.patch b/queue-6.18/spi-uniphier-fix-controller-deregistration.patch
new file mode 100644 (file)
index 0000000..63bfb61
--- /dev/null
@@ -0,0 +1,59 @@
+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[] = {
diff --git a/queue-6.18/spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch b/queue-6.18/spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch
new file mode 100644 (file)
index 0000000..018b5d8
--- /dev/null
@@ -0,0 +1,99 @@
+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[] = {
diff --git a/queue-6.18/spi-zynq-qspi-fix-controller-deregistration.patch b/queue-6.18/spi-zynq-qspi-fix-controller-deregistration.patch
new file mode 100644 (file)
index 0000000..fae9ff3
--- /dev/null
@@ -0,0 +1,73 @@
+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[] = {
diff --git a/queue-6.18/spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch b/queue-6.18/spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch
new file mode 100644 (file)
index 0000000..8eeabf9
--- /dev/null
@@ -0,0 +1,142 @@
+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[] = {
diff --git a/queue-6.18/usb-dwc3-add-dwc-pointer-to-dwc3_readl-writel.patch b/queue-6.18/usb-dwc3-add-dwc-pointer-to-dwc3_readl-writel.patch
new file mode 100644 (file)
index 0000000..81658ba
--- /dev/null
@@ -0,0 +1,1699 @@
+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);
+ }
diff --git a/queue-6.18/usb-dwc3-move-guid-programming-after-phy-initialization.patch b/queue-6.18/usb-dwc3-move-guid-programming-after-phy-initialization.patch
new file mode 100644 (file)
index 0000000..9aec55e
--- /dev/null
@@ -0,0 +1,62 @@
+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);
diff --git a/queue-6.18/usb-dwc3-remove-of-dep-regs.patch b/queue-6.18/usb-dwc3-remove-of-dep-regs.patch
new file mode 100644 (file)
index 0000000..24c0fc4
--- /dev/null
@@ -0,0 +1,146 @@
+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);
+ }
diff --git a/queue-6.18/usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch b/queue-6.18/usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch
new file mode 100644 (file)
index 0000000..e541289
--- /dev/null
@@ -0,0 +1,85 @@
+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;