[PATCH] regmap-irq: Use the new num_config_regs property in regmap_add_irq_chip_fwnode

From: Yassine Oudjana
Date: Mon Nov 07 2022 - 15:21:43 EST


From: Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx>

Commit faa87ce9196d ("regmap-irq: Introduce config registers for irq
types") added the num_config_regs, then commit 9edd4f5aee84 ("regmap-irq:
Deprecate type registers and virtual registers") suggested to replace
num_type_reg with it. However, regmap_add_irq_chip_fwnode wasn't modified
to use the new property. Later on, commit 255a03bb1bb3 ("ASoC: wcd9335:
Convert irq chip to config regs") removed the old num_type_reg property
from the WCD9335 driver's struct regmap_irq_chip, causing a null pointer
dereference in regmap_irq_set_type when it tried to index d->type_buf as
it was never allocated in regmap_add_irq_chip_fwnode:

[ 39.199374] Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
[ 39.199383] Mem abort info:
[ 39.199390] ESR = 0x0000000096000004
[ 39.199397] EC = 0x25: DABT (current EL), IL = 32 bits
[ 39.199408] SET = 0, FnV = 0
[ 39.199415] EA = 0, S1PTW = 0
[ 39.199422] FSC = 0x04: level 0 translation fault
[ 39.199430] Data abort info:
[ 39.199436] ISV = 0, ISS = 0x00000004
[ 39.199443] CM = 0, WnR = 0
[ 39.199449] user pgtable: 4k pages, 48-bit VAs, pgdp=0000000084549000
[ 39.199458] [0000000000000000] pgd=0000000000000000, p4d=0000000000000000
[ 39.199474] Internal error: Oops: 0000000096000004 [#1] PREEMPT SMP
[ 39.199483] Modules linked in: snd_soc_wcd9335 regmap_slimbus panel_lgphilips_sw43101 ath10k_pci ath10k_core q6asm_dai msm venus_dec venus_enc ath q6routing q6afe_dai videobuf2_dma_contig mac80211 snd_soc_apq8096 q6asm q6adm snd_soc_qcom_common snd_q6dsp_common q6afe snd_soc_core q6core drm_dp_aux_bus ak7375 imx318 gpu_sched apr snd_compress libarc4 qcom_camss soundwire_bus v4l2_fwnode venus_core v4l2_async snd_pcm drm_display_helper videobuf2_dma_sg v4l2_mem2mem videobuf2_memops nxp_nci_i2c drm_kms_helper videobuf2_v4l2 nxp_nci hci_uart snd_timer btqca syscopyarea videobuf2_common nci snd sysfillrect videodev slim_qcom_ngd_ctrl soundcore sysimgblt nfc bluetooth pdr_interface fb_sys_fops mc i2c_qcom_cci lzo_rle slimbus qcom_spmi_haptics qcom_q6v5_pas qcom_q6v5_mss qcom_pil_info qcom_common qcom_q6v5 qcom_sysmon qmi_helpers socinfo mdt_loader pwm_ir_tx rmtfs_mem cfg80211 rfkill zram zsmalloc atmel_mxt_ts drm drm_panel_orientation_quirks ip_tables
[ 39.199764] CPU: 0 PID: 214 Comm: kworker/u8:5 Tainted: G W 6.1.0-rc4+ #98
[ 39.199775] Hardware name: Xiaomi Mi Note 2 (DT)
[ 39.199784] Workqueue: events_unbound deferred_probe_work_func
[ 39.199809] pstate: 400000c5 (nZcv daIF -PAN -UAO -TCO -DIT -SSBS BTYPE=--)
[ 39.199819] pc : regmap_irq_set_type+0x84/0x1c0
[ 39.199833] lr : regmap_irq_set_type+0x58/0x1c0
[ 39.199846] sp : ffff80000b813810
[ 39.199852] x29: ffff80000b813810 x28: 0000000000000000 x27: ffff8000256b5df0
[ 39.199869] x26: 0000000000000000 x25: ffff0000b12ad400 x24: ffff0000044ee660
[ 39.199884] x23: 0000000000000000 x22: ffff800025691868 x21: 0000000000000001
[ 39.199900] x20: ffff800025691870 x19: ffff000002d04e00 x18: ffffffffffffffff
[ 39.199915] x17: 0000000000000000 x16: ffff800008153b10 x15: 0000000000000006
[ 39.199930] x14: 0000000000000000 x13: ffff800009216eb0 x12: 0000000000000831
[ 39.199945] x11: 00000000000002bb x10: ffff80000926eeb0 x9 : ffff800009216eb0
[ 39.199960] x8 : 00000000ffffefff x7 : ffff80000926eeb0 x6 : 80000000fffff000
[ 39.199975] x5 : ffff0000fdce09d0 x4 : 0000000000000000 x3 : 0000000000000000
[ 39.199991] x2 : 0000000000000000 x1 : 0000000000000001 x0 : 0000000000000001
[ 39.200006] Call trace:
[ 39.200014] regmap_irq_set_type+0x84/0x1c0
[ 39.200026] __irq_set_trigger+0x60/0x1c0
[ 39.200040] __setup_irq+0x2f4/0x78c
[ 39.200051] request_threaded_irq+0xe8/0x1a0
[ 39.200063] devm_request_threaded_irq+0x80/0x100
[ 39.200074] wcd9335_codec_probe+0x21c/0x2f0 [snd_soc_wcd9335]
[ 39.200098] snd_soc_component_probe+0x28/0x7c [snd_soc_core]
[ 39.200167] soc_probe_component+0x1cc/0x380 [snd_soc_core]
[ 39.200206] snd_soc_bind_card+0x45c/0xc80 [snd_soc_core]
[ 39.200244] snd_soc_register_card+0xf0/0x110 [snd_soc_core]
[ 39.200283] devm_snd_soc_register_card+0x4c/0xa4 [snd_soc_core]
[ 39.200334] apq8096_platform_probe+0xd0/0xf0 [snd_soc_apq8096]
[ 39.200353] platform_probe+0x68/0xc0
[ 39.200366] really_probe+0xc0/0x3dc
[ 39.200375] __driver_probe_device+0x7c/0x190
[ 39.200384] driver_probe_device+0x3c/0x110
[ 39.200392] __device_attach_driver+0xbc/0x160
[ 39.200401] bus_for_each_drv+0x78/0xd0
[ 39.200414] __device_attach+0x9c/0x1c0
[ 39.200422] device_initial_probe+0x14/0x20
[ 39.200431] bus_probe_device+0x9c/0xa4
[ 39.200441] deferred_probe_work_func+0x9c/0xf0
[ 39.200456] process_one_work+0x1d4/0x330
[ 39.200471] worker_thread+0x6c/0x430
[ 39.200481] kthread+0x108/0x10c
[ 39.200490] ret_from_fork+0x10/0x20
[ 39.200507] Code: f940c663 b9400681 1ac00af7 937e7ee4 (b8646860)
[ 39.200518] ---[ end trace 0000000000000000 ]---

Use num_config_regs in regmap_add_irq_chip_fwnode instead of num_type_reg,
and fall back to it if num_config_regs isn't defined to maintain backward
compatibility.

Fixes: faa87ce9196d ("regmap-irq: Introduce config registers for irq types")
Signed-off-by: Yassine Oudjana <y.oudjana@xxxxxxxxxxxxxx>
---
drivers/base/regmap/regmap-irq.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c
index 4ef9488d05cd..3de89795f584 100644
--- a/drivers/base/regmap/regmap-irq.c
+++ b/drivers/base/regmap/regmap-irq.c
@@ -722,6 +722,7 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
int i;
int ret = -ENOMEM;
int num_type_reg;
+ int num_regs;
u32 reg;

if (chip->num_regs <= 0)
@@ -796,14 +797,20 @@ int regmap_add_irq_chip_fwnode(struct fwnode_handle *fwnode,
goto err_alloc;
}

- num_type_reg = chip->type_in_mask ? chip->num_regs : chip->num_type_reg;
- if (num_type_reg) {
- d->type_buf_def = kcalloc(num_type_reg,
+ /*
+ * Use num_config_regs if defined, otherwise fall back to num_type_reg
+ * to maintain backward compatibility.
+ */
+ num_type_reg = chip->num_config_regs ? chip->num_config_regs
+ : chip->num_type_reg;
+ num_regs = chip->type_in_mask ? chip->num_regs : num_type_reg;
+ if (num_regs) {
+ d->type_buf_def = kcalloc(num_regs,
sizeof(*d->type_buf_def), GFP_KERNEL);
if (!d->type_buf_def)
goto err_alloc;

- d->type_buf = kcalloc(num_type_reg, sizeof(*d->type_buf),
+ d->type_buf = kcalloc(num_regs, sizeof(*d->type_buf),
GFP_KERNEL);
if (!d->type_buf)
goto err_alloc;
--
2.38.1