From: Greg Kroah-Hartman Date: Fri, 15 May 2026 09:30:20 +0000 (+0200) Subject: 6.18-stable patches X-Git-Tag: v5.10.256~8 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=145e3399f7b73a34306902c8c012248459356019;p=thirdparty%2Fkernel%2Fstable-queue.git 6.18-stable patches 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 --- 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 index 0000000000..4e88f8dbb5 --- /dev/null +++ b/queue-6.18/block-fix-zone-write-plug-removal.patch @@ -0,0 +1,294 @@ +From stable+bounces-247236-greg=kroah.com@vger.kernel.org Thu May 14 17:55:29 2026 +From: Sasha Levin +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 , Christoph Hellwig , Johannes Thumshirn , Jens Axboe , Sasha Levin +Message-ID: <20260514155220.306649-1-sashal@kernel.org> + +From: Damien Le Moal + +[ 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 +Reviewed-by: Christoph Hellwig +Reviewed-by: Johannes Thumshirn +Signed-off-by: Jens Axboe +[ dropped upstream blk_zone_set_cond() call and disk_zone_wplug_update_cond() context line ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..684fc93069 --- /dev/null +++ b/queue-6.18/bluetooth-hci_conn-fix-potential-uaf-in-create_big_sync.patch @@ -0,0 +1,96 @@ +From stable+bounces-246958-greg=kroah.com@vger.kernel.org Wed May 13 19:37:21 2026 +From: Sasha Levin +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 , Luiz Augusto von Dentz , Sasha Levin +Message-ID: <20260513171003.3829583-1-sashal@kernel.org> + +From: David Carlier + +[ 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 +Signed-off-by: Luiz Augusto von Dentz +Signed-off-by: David Carlier +Signed-off-by: Luiz Augusto von Dentz +[ 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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..8645b2532d --- /dev/null +++ b/queue-6.18/drm-amdgpu-fix-validating-flush_gpu_tlb_pasid.patch @@ -0,0 +1,47 @@ +From e3a6eff92bbd960b471966d9afccb4d584546d17 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Timur=20Krist=C3=B3f?= +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 + +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 +Reported-by: Dan Carpenter +Closes: https://lore.kernel.org/r/202601190121.z9C0uml5-lkp@intel.com/ +Signed-off-by: Timur Kristóf +Signed-off-by: Prike Liang +Reviewed-by: Prike Liang +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..8c8b103603 --- /dev/null +++ b/queue-6.18/drm-amdgpu-rework-how-we-handle-tlb-fences.patch @@ -0,0 +1,75 @@ +From 69c5fbd2b93b5ced77c6e79afe83371bca84c788 Mon Sep 17 00:00:00 2001 +From: Alex Deucher +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 + +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 +Cc: Prike Liang +Reviewed-by: Prike Liang +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..d1829bec34 --- /dev/null +++ b/queue-6.18/drm-amdgpu-validate-the-flush_gpu_tlb_pasid.patch @@ -0,0 +1,35 @@ +From f4db9913e4d3dabe9ff3ea6178f2c1bc286012b8 Mon Sep 17 00:00:00 2001 +From: Prike Liang +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 + +commit f4db9913e4d3dabe9ff3ea6178f2c1bc286012b8 upstream. + +Validate flush_gpu_tlb_pasid() availability before flushing tlb. + +Signed-off-by: Prike Liang +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..d2180f36ba --- /dev/null +++ b/queue-6.18/edac-versalnet-fix-device-name-memory-leak.patch @@ -0,0 +1,52 @@ +From stable+bounces-247237-greg=kroah.com@vger.kernel.org Thu May 14 17:52:38 2026 +From: Sasha Levin +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 , "Borislav Petkov (AMD)" , Sasha Levin +Message-ID: <20260514155232.307214-1-sashal@kernel.org> + +From: Prasanna Kumar T S M + +[ 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 +Signed-off-by: Borislav Petkov (AMD) +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..fc6675dbec --- /dev/null +++ b/queue-6.18/fbcon-avoid-oob-font-access-if-console-rotation-fails.patch @@ -0,0 +1,55 @@ +From stable+bounces-247267-greg=kroah.com@vger.kernel.org Thu May 14 19:58:56 2026 +From: Sasha Levin +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 , Helge Deller , Sasha Levin +Message-ID: <20260514175845.529279-2-sashal@kernel.org> + +From: Thomas Zimmermann + +[ 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 +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 +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..27b2030923 --- /dev/null +++ b/queue-6.18/fbcon-rename-struct-fbcon_ops-to-struct-fbcon_par.patch @@ -0,0 +1,2459 @@ +From stable+bounces-247266-greg=kroah.com@vger.kernel.org Thu May 14 19:58:52 2026 +From: Sasha Levin +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 , Sam Ravnborg , Sasha Levin +Message-ID: <20260514175845.529279-1-sashal@kernel.org> + +From: Thomas Zimmermann + +[ 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 +Reviewed-by: Sam Ravnborg +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 +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..f13de81a06 --- /dev/null +++ b/queue-6.18/loongarch-kvm-compile-switch.s-directly-into-the-kernel.patch @@ -0,0 +1,264 @@ +From 5203012fa6045aac4b69d4e7c212e16dcf38ef10 Mon Sep 17 00:00:00 2001 +From: Xianglai Li +Date: Mon, 4 May 2026 09:00:37 +0800 +Subject: LoongArch: KVM: Compile switch.S directly into the kernel + +From: Xianglai Li + +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 +Signed-off-by: Huacai Chen +Signed-off-by: Greg Kroah-Hartman +--- + 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 ++#include + #include + #include + #include ++#include + #include + #include + +@@ -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 index 0000000000..1eb2fea108 --- /dev/null +++ b/queue-6.18/mm-damon-core-disallow-time-quota-setting-zero-esz.patch @@ -0,0 +1,88 @@ +From 8bbde987c2b84f80da0853f739f0a920386f8b99 Mon Sep 17 00:00:00 2001 +From: SeongJae Park +Date: Mon, 6 Apr 2026 17:31:52 -0700 +Subject: mm/damon/core: disallow time-quota setting zero esz + +From: SeongJae Park + +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 +Cc: # 5.16.x +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..8ff8b7cb20 --- /dev/null +++ b/queue-6.18/mm-damon-core-implement-damon_kdamond_pid.patch @@ -0,0 +1,86 @@ +From 4262c53236977de3ceaa3bf2aefdf772c9b874dd Mon Sep 17 00:00:00 2001 +From: SeongJae Park +Date: Thu, 15 Jan 2026 07:20:41 -0800 +Subject: mm/damon/core: implement damon_kdamond_pid() + +From: SeongJae Park + +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 +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..3e15d136c7 --- /dev/null +++ b/queue-6.18/mm-damon-lru_sort-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch @@ -0,0 +1,220 @@ +From b98b7ff6025ae82570d4915e083f0cbd8d48b3cf Mon Sep 17 00:00:00 2001 +From: SeongJae Park +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 + +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 +Signed-off-by: Liew Rui Yan +Signed-off-by: SeongJae Park +Cc: # 6.0.x +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..09290e2268 --- /dev/null +++ b/queue-6.18/mm-damon-reclaim-detect-and-use-fresh-enabled-and-kdamond_pid-values.patch @@ -0,0 +1,241 @@ +From 64a140afa5ed1c6f5ba6d451512cbdbbab1ba339 Mon Sep 17 00:00:00 2001 +From: SeongJae Park +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 + +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 +Signed-off-by: Liew Rui Yan +Signed-off-by: SeongJae Park +Cc: # 5.19.x +Signed-off-by: Andrew Morton +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..e5de4f8cbd --- /dev/null +++ b/queue-6.18/papr-hvpipe-convert-papr_hvpipe_dev_create_handle-to-fd_prepare.patch @@ -0,0 +1,89 @@ +From stable+bounces-247227-greg=kroah.com@vger.kernel.org Thu May 14 17:10:50 2026 +From: Sasha Levin +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 , Sasha Levin +Message-ID: <20260514150820.274333-1-sashal@kernel.org> + +From: Christian Brauner + +[ 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 +Stable-dep-of: 7a4f0846ee6c ("pseries/papr-hvpipe: Fix race with interrupt handler") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..eec39181f9 --- /dev/null +++ b/queue-6.18/pseries-papr-hvpipe-fix-race-with-interrupt-handler.patch @@ -0,0 +1,107 @@ +From stable+bounces-247228-greg=kroah.com@vger.kernel.org Thu May 14 17:16:59 2026 +From: Sasha Levin +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)" , Madhavan Srinivasan , Sasha Levin +Message-ID: <20260514150820.274333-2-sashal@kernel.org> + +From: "Ritesh Harjani (IBM)" + +[ 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) +Signed-off-by: Madhavan Srinivasan +Link: https://patch.msgid.link/e4ed435c44fc191f2eb23c7907ba6f72f193e6aa.1777606826.git.ritesh.list@gmail.com +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..ecd74ff63e --- /dev/null +++ b/queue-6.18/revert-drm-amdgpu-don-t-attach-the-tlb-fence-for-si.patch @@ -0,0 +1,42 @@ +From 9163fe4d790fb4e16d6b0e23f55b43cddd3d4a65 Mon Sep 17 00:00:00 2001 +From: Prike Liang +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 + +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 +Reviewed-by: Christian König +Signed-off-by: Alex Deucher +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..a6e59a5cc5 --- /dev/null +++ b/queue-6.18/sched-ext-implement-cgroup_set_idle-callback.patch @@ -0,0 +1,120 @@ +From stable+bounces-246937-greg=kroah.com@vger.kernel.org Wed May 13 19:04:56 2026 +From: Sasha Levin +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 , zhidao su , Tejun Heo , Sasha Levin +Message-ID: <20260513163322.3807202-1-sashal@kernel.org> + +From: zhidao su + +[ 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 +Signed-off-by: Tejun Heo +Stable-dep-of: 80afd4c84bc8 ("sched_ext: Read scx_root under scx_cgroup_ops_rwsem in cgroup setters") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..6bf1aed967 --- /dev/null +++ b/queue-6.18/sched_ext-read-scx_root-under-scx_cgroup_ops_rwsem-in-cgroup-setters.patch @@ -0,0 +1,72 @@ +From stable+bounces-246938-greg=kroah.com@vger.kernel.org Wed May 13 18:42:02 2026 +From: Sasha Levin +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 , Chris Mason , Andrea Righi , Sasha Levin +Message-ID: <20260513163322.3807202-2-sashal@kernel.org> + +From: Tejun Heo + +[ 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 +Signed-off-by: Tejun Heo +Reviewed-by: Andrea Righi +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 || diff --git a/queue-6.18/series b/queue-6.18/series index 876fb5a108..1082766207 100644 --- a/queue-6.18/series +++ b/queue-6.18/series @@ -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 index 0000000000..1fa0c6aa55 --- /dev/null +++ b/queue-6.18/spi-tegra114-fix-controller-deregistration.patch @@ -0,0 +1,59 @@ +From stable+bounces-247094-greg=kroah.com@vger.kernel.org Thu May 14 05:10:44 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 23:10:37 -0400 +Subject: spi: tegra114: fix controller deregistration +To: stable@vger.kernel.org +Cc: Johan Hovold , Jingoo Han , Mark Brown , Sasha Levin +Message-ID: <20260514031037.4119194-1-sashal@kernel.org> + +From: Johan Hovold + +[ 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 +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-22-johan@kernel.org +Signed-off-by: Mark Brown +[ kept `host->dev.of_node = pdev->dev.of_node;` context line above the `spi_register_controller()` conversion ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..9a2a895e8a --- /dev/null +++ b/queue-6.18/spi-tegra20-sflash-fix-controller-deregistration.patch @@ -0,0 +1,57 @@ +From stable+bounces-247099-greg=kroah.com@vger.kernel.org Thu May 14 06:16:21 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 00:14:46 -0400 +Subject: spi: tegra20-sflash: fix controller deregistration +To: stable@vger.kernel.org +Cc: Johan Hovold , Jingoo Han , Mark Brown , Sasha Levin +Message-ID: <20260514041446.4193882-1-sashal@kernel.org> + +From: Johan Hovold + +[ 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 +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-23-johan@kernel.org +Signed-off-by: Mark Brown +[ kept the redundant `host->dev.of_node = pdev->dev.of_node;` line above the registration call ] +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..63bfb614da --- /dev/null +++ b/queue-6.18/spi-uniphier-fix-controller-deregistration.patch @@ -0,0 +1,59 @@ +From stable+bounces-247110-greg=kroah.com@vger.kernel.org Thu May 14 06:58:43 2026 +From: Sasha Levin +Date: Thu, 14 May 2026 00:58:33 -0400 +Subject: spi: uniphier: fix controller deregistration +To: stable@vger.kernel.org +Cc: Johan Hovold , Keiji Hayashibara , Mark Brown , Sasha Levin +Message-ID: <20260514045833.24151-2-sashal@kernel.org> + +From: Johan Hovold + +[ 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 +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-25-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..018b5d85e7 --- /dev/null +++ b/queue-6.18/spi-uniphier-simplify-clock-handling-with-devm_clk_get_enabled.patch @@ -0,0 +1,99 @@ +From stable+bounces-247109-greg=kroah.com@vger.kernel.org Thu May 14 06:58:44 2026 +From: Sasha Levin +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 , Kunihiko Hayashi , Mark Brown , Sasha Levin +Message-ID: <20260514045833.24151-1-sashal@kernel.org> + +From: Pei Xiao + +[ 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 +Reviewed-by: Kunihiko Hayashi +Link: https://patch.msgid.link/b2deeefd4ef1a4bce71116aabfcb7e81400f6d37.1775546948.git.xiaopei01@kylinos.cn +Signed-off-by: Mark Brown +Stable-dep-of: 0245435f7772 ("spi: uniphier: fix controller deregistration") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..fae9ff3bb3 --- /dev/null +++ b/queue-6.18/spi-zynq-qspi-fix-controller-deregistration.patch @@ -0,0 +1,73 @@ +From stable+bounces-246994-greg=kroah.com@vger.kernel.org Wed May 13 20:15:39 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 14:08:36 -0400 +Subject: spi: zynq-qspi: fix controller deregistration +To: stable@vger.kernel.org +Cc: Johan Hovold , Naga Sureshkumar Relli , Mark Brown , Sasha Levin +Message-ID: <20260513180836.3912674-2-sashal@kernel.org> + +From: Johan Hovold + +[ 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 +Signed-off-by: Johan Hovold +Link: https://patch.msgid.link/20260410081757.503099-27-johan@kernel.org +Signed-off-by: Mark Brown +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..8eeabf9b8f --- /dev/null +++ b/queue-6.18/spi-zynq-qspi-simplify-clock-handling-with-devm_clk_get_enabled.patch @@ -0,0 +1,142 @@ +From stable+bounces-246993-greg=kroah.com@vger.kernel.org Wed May 13 20:15:37 2026 +From: Sasha Levin +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 , Michal Simek , Mark Brown , Sasha Levin +Message-ID: <20260513180836.3912674-1-sashal@kernel.org> + +From: Pei Xiao + +[ 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 +Acked-by: Michal Simek +Link: https://patch.msgid.link/24043625f89376da36feca2408f990a85be7ab36.1775555500.git.xiaopei01@kylinos.cn +Signed-off-by: Mark Brown +Stable-dep-of: c9c012706c9f ("spi: zynq-qspi: fix controller deregistration") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..81658baf4e --- /dev/null +++ b/queue-6.18/usb-dwc3-add-dwc-pointer-to-dwc3_readl-writel.patch @@ -0,0 +1,1699 @@ +From sashal@kernel.org Wed May 13 13:27:49 2026 +From: Sasha Levin +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 , Thinh Nguyen , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260513112744.3646168-2-sashal@kernel.org> + +From: Prashanth K + +[ 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 +Acked-by: Thinh Nguyen +Link: https://patch.msgid.link/20260114100748.2950103-3-prashanth.k@oss.qualcomm.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: aad35f9c926e ("usb: dwc3: Move GUID programming after PHY initialization") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..9aec55eac4 --- /dev/null +++ b/queue-6.18/usb-dwc3-move-guid-programming-after-phy-initialization.patch @@ -0,0 +1,62 @@ +From stable+bounces-246815-greg=kroah.com@vger.kernel.org Wed May 13 13:27:53 2026 +From: Sasha Levin +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 , stable , Pritam Manohar Sutar , Thinh Nguyen , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260513112744.3646168-3-sashal@kernel.org> + +From: Selvarasu Ganesan + +[ 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 +Reported-by: Pritam Manohar Sutar +Signed-off-by: Selvarasu Ganesan +Acked-by: Thinh Nguyen +Link: https://patch.msgid.link/20260417063314.2359-1-selvarasu.g@samsung.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..24c0fc4980 --- /dev/null +++ b/queue-6.18/usb-dwc3-remove-of-dep-regs.patch @@ -0,0 +1,146 @@ +From sashal@kernel.org Wed May 13 13:27:48 2026 +From: Sasha Levin +Date: Wed, 13 May 2026 07:27:42 -0400 +Subject: usb: dwc3: Remove of dep->regs +To: stable@vger.kernel.org +Cc: Prashanth K , Thinh Nguyen , Greg Kroah-Hartman , Sasha Levin +Message-ID: <20260513112744.3646168-1-sashal@kernel.org> + +From: Prashanth K + +[ 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 +Acked-by: Thinh Nguyen +Link: https://patch.msgid.link/20260114100748.2950103-2-prashanth.k@oss.qualcomm.com +Signed-off-by: Greg Kroah-Hartman +Stable-dep-of: aad35f9c926e ("usb: dwc3: Move GUID programming after PHY initialization") +Signed-off-by: Sasha Levin +Signed-off-by: Greg Kroah-Hartman +--- + 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 index 0000000000..e541289731 --- /dev/null +++ b/queue-6.18/usb-typec-tcpm-reset-internal-port-states-on-soft-reset-ams.patch @@ -0,0 +1,85 @@ +From 2909f0d4994fb4306bf116df5ccee797791fce2c Mon Sep 17 00:00:00 2001 +From: Amit Sunil Dhamne +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 + +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 +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 +Reviewed-by: Badhri Jagan Sridharan +Acked-by: Heikki Krogerus +Link: https://patch.msgid.link/20260414-fix-soft-reset-v1-1-01d7cb9764e2@google.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Greg Kroah-Hartman +--- + 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;