media: camera: cdi-mgr: Fix crash freeing GPIOs

When booting Linux v6.10-rc5 on Tegra234 the CDI MGR driver was failing
to setup the GPIOs. If the driver fails to setup the GPIOs then we
expect the probe of the driver to fail. However, in this case when the
probe failed, it then crashed the kernel completely and the following
crash log was observed ...

 cdi-mgr sipl_devblk_3: cdi_mgr_configure_gpios Failed to allocate gpio
  desc
 cdi-mgr sipl_devblk_3: cdi_mgr_probe(): GPIO setup failed
 Unable to handle kernel NULL pointer dereference at virtual address
  0000000000000300
 ...
 Call trace:
  rt_spin_lock+0x24/0xa8
  devres_remove+0x38/0x174
  devres_release+0x1c/0x80
  devm_gpiod_put+0x24/0x4c
  cdi_delete_lst+0x18c/0x1200 [cdi_mgr]
  cdi_mgr_debugfs_init+0x608/0x11b0 [cdi_mgr]
  platform_probe+0x64/0xec
  really_probe+0xb8/0x284
  __driver_probe_device+0x74/0x12c
  driver_probe_device+0x38/0x114
  __driver_attach+0x74/0x13c
  bus_for_each_dev+0x74/0xf0
  driver_attach+0x20/0x30
  bus_add_driver+0xe4/0x20c
  driver_register+0x5c/0x130
  __platform_driver_register+0x24/0x34
  init_module+0x1c/0x1000 [cdi_mgr]
  do_one_initcall+0x44/0x2e8
  do_init_module+0x58/0x1f8
  load_module+0x1b94/0x1cf8
  init_module_from_file+0x84/0xc8
  __arm64_sys_finit_module+0x1b8/0x270
  invoke_syscall+0x40/0x11c
  el0_svc_common.constprop.0+0xc4/0xe4
  do_el0_svc+0x18/0x28
  el0_svc+0x30/0xe0
  el0t_64_sync_handler+0xc8/0xcc
  el0t_64_sync+0x16c/0x170
 Code: b9447420 d503201f 91006262 d2800000 (c8e07c41)
 ---[ end trace 0000000000000000]---

The problem is that the CDI MGR allocated the gpio descriptors by
calling the function devm_fwnode_gpiod_get_index(). This function
returns an ERR_PTR() on failure. When this does fail and cdi_mgr_del()
is called to clean-up, this does not check to see if the descriptor
IS_ERR(), but simply check if it is NULL or not, which is not correct.
Hence, we end up calling devm_gpiod_put() for an invalid descriptor and
the above crash is observed. Given that we are calling
devm_fwnode_gpiod_get_index() to allocate the descriptor, it is not
necessary to call devm_gpiod_put() at all, because the kernel will
automtically call this for us. Therefore, fix this by removing the call
to devm_gpiod_put() completely.

Please note that although this was caught with Linux v6.10-rc5, this is
applicable to all kernel versions.

Bug 4627271

Change-Id: I576a984ebaaeea590c5acea1b489284379832ae9
Signed-off-by: Jon Hunter <jonathanh@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3148004
Reviewed-by: Frank Chen <frankc@nvidia.com>
This commit is contained in:
Jon Hunter
2024-05-30 13:05:09 +01:00
committed by mobile promotions
parent 5626a33be3
commit 27bc2f4757

View File

@@ -1277,11 +1277,6 @@ static void cdi_mgr_del(struct cdi_mgr_priv *cdi_mgr)
if (cdi_mgr->tca9539.enable)
i2c_put_adapter(cdi_mgr->tca9539.adap);
i2c_put_adapter(cdi_mgr->adap);
for (i = 0; i < MAX_CDI_GPIOS; i++) {
if (cdi_mgr->gpios[i].desc)
devm_gpiod_put(cdi_mgr->dev, cdi_mgr->gpios[i].desc);
}
}
static void cdi_mgr_dev_ins(struct work_struct *work)