Re: [PATCH v4 1/1] regmap: Synchronize cache for the page selector

From: Marek Szyprowski

Date: Wed Feb 18 2026 - 03:31:00 EST


On 18.02.2026 08:46, Andy Shevchenko wrote:
> If the selector register is represented in each page, its value
> according to the debugfs is stale because it gets synchronized
> only after the real page switch happens. Hence the regmap cache
> initialisation from the HW inherits outdated data in the selector
> register.
>
> Synchronize cache for the page selector just in time.
>
> Before (offset followed by hexdump, the first byte is selector):
>
> // Real registers
> 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
> ...
> // Virtual (per port)
> 40: 05 ff 00 00 e0 e0 00 00 00 00 00 1f
> 50: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
> 60: 01 ff 00 00 ff ff 00 00 00 00 00 00
> 70: 02 ff 00 00 cf f3 00 00 00 00 00 0c
> 80: 03 ff 00 00 00 00 00 00 00 00 00 ff
> 90: 04 ff 00 00 ff 0f 00 00 f0 00 00 00
>
> After:
>
> // Real registers
> 18: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
> ...
> // Virtual (per port)
> 40: 00 ff 00 00 e0 e0 00 00 00 00 00 1f
> 50: 01 ff 00 00 e0 e0 00 00 00 00 00 1f
> 60: 02 ff 00 00 ff ff 00 00 00 00 00 00
> 70: 03 ff 00 00 cf f3 00 00 00 00 00 0c
> 80: 04 ff 00 00 00 00 00 00 00 00 00 ff
> 90: 05 ff 00 00 ff 0f 00 00 f0 00 00 00
>
> Fixes: 6863ca622759 ("regmap: Add support for register indirect addressing.")
> Signed-off-by: Andy Shevchenko <andriy.shevchenko@xxxxxxxxxxxxxxx>
> ---
> v4: reworked the approach completely
>
> Marek, Dmitry,
> Please, test on your HW to be sure this will have no side effects
> in your case with LT9611.

It looks that it ends in infinite recurrent calls after this patch:

Insufficient stack space to handle exception!
ESR: 0x0000000096000047 -- DABT (current EL)
FAR: 0xffff8000859bffe0
Task stack:     [0xffff8000859c0000..0xffff8000859c4000]
IRQ stack:      [0xffff800080030000..0xffff800080034000]
Overflow stack: [0xffff0001fef36140..0xffff0001fef37140]
CPU: 6 UID: 0 PID: 341 Comm: (udev-worker) Not tainted
6.19.0-next-20260217+ #12215 PREEMPT
Hardware name: Qualcomm Technologies, Inc. Robotics RB5 (DT)
pstate: 80400005 (Nzcv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--)
pc : _regmap_select_page+0x4/0x120
lr : _regmap_raw_read+0x240/0x340
...
Kernel panic - not syncing: kernel stack overflow
CPU: 6 UID: 0 PID: 341 Comm: (udev-worker) Not tainted
6.19.0-next-20260217+ #12215 PREEMPT
Hardware name: Qualcomm Technologies, Inc. Robotics RB5 (DT)
Call trace:
 show_stack+0x18/0x24 (C)
 dump_stack_lvl+0x38/0xd0
 dump_stack+0x18/0x24
 vpanic+0x4f8/0x4fc
 do_panic_on_target_cpu+0x0/0x1c
 add_taint+0x0/0xbc
 panic_bad_stack+0x104/0x124
 __sdei_handler+0x0/0x2c4
 __bad_stack+0x80/0x84
 _regmap_select_page+0x4/0x120 (P)
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_read+0x240/0x340
 _regmap_bus_read+0x44/0x7c
 _regmap_read+0x64/0x1f0
 _regmap_update_bits+0xec/0x134
 _regmap_select_page+0x9c/0x120
 _regmap_raw_write_impl+0x414/0x7b8
 _regmap_bus_raw_write+0x60/0x7c
 _regmap_write+0x60/0x1b8
 regmap_write+0x4c/0x78
 lt9611uxc_probe+0x208/0x684 [lontium_lt9611uxc]
 i2c_device_probe+0x154/0x344
 really_probe+0xbc/0x298
 __driver_probe_device+0x78/0x12c
 driver_probe_device+0x40/0x164
 __driver_attach+0xe4/0x224
 bus_for_each_dev+0x74/0xd0
 driver_attach+0x24/0x30
 bus_add_driver+0xe4/0x208
 driver_register+0x60/0x128
 i2c_register_driver+0x48/0xd0
 lt9611uxc_driver_init+0x20/0x1000 [lontium_lt9611uxc]
 do_one_initcall+0x64/0x504
 do_init_module+0x58/0x23c
 load_module+0x1b48/0x1e64
 init_module_from_file+0xd4/0xec
 idempotent_init_module+0x188/0x280
 __arm64_sys_finit_module+0x68/0xac
 invoke_syscall+0x48/0x10c
 el0_svc_common.constprop.0+0xc8/0xe8
 do_el0_svc+0x20/0x2c
 el0_svc+0x50/0x2e8
 el0t_64_sync_handler+0xa0/0xe4
 el0t_64_sync+0x198/0x19c
SMP: stopping secondary CPUs



> drivers/base/regmap/regmap.c | 14 +++++++++++---
> 1 file changed, 11 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
> index 5d5a3e115022..1b90f00a5005 100644
> --- a/drivers/base/regmap/regmap.c
> +++ b/drivers/base/regmap/regmap.c
> @@ -1525,10 +1525,18 @@ static int _regmap_select_page(struct regmap *map, unsigned int *reg,
> return -EINVAL;
> }
>
> - /* It is possible to have selector register inside data window.
> - In that case, selector register is located on every page and
> - it needs no page switching, when accessed alone. */
> + /*
> + * It is possible to have selector register inside data window.
> + * In that case, selector register is located on every page and it
> + * needs no page switching, when accessed alone.
> + *
> + * Nevertheless we should synchronize the cache values for it.
> + * This can't be properly achieved if the selector register is
> + * the first and the only one to be read inside the data window.
> + * That's why we update it in that case as well.
> + */
> if (val_num > 1 ||
> + in_range(range->selector_reg, range->window_start, range->window_len) ||
> range->window_start + win_offset != range->selector_reg) {
> /* Use separate work_buf during page switching */
> orig_work_buf = map->work_buf;

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland