On 12.05.2022 10:23, Vladimir Zapolskiy wrote: > To simplify the driver's maintenance it makes sense to escape from > hardcoded numbers of power domain resources per platform and statical > allocation of the resources. For instance on a QCOM SM8450 platform > the number of CAMSS power domains shall be bumped up to 6, also notably > CAMSS on MSM8916 has only one power domain, however it expects to get 2, > and thus it should result in a runtime error on driver probe. > > The change fixes an issue mentioned above and gives more flexibility > to support more platforms in future. > > Signed-off-by: Vladimir Zapolskiy <vladimir.zapolskiy@xxxxxxxxxx> This patch landed recently in linux next-20220616 as commit f673698ceee5 ("media: camss: Allocate power domain resources dynamically"). Unfortunately it causes serious issues on DragonBoard 410c SBC (arch/arm64/boot/dts/qcom/apq8016-sbc.dts), like multiple 'Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000'. The problem originates in camss_configure_pd() function. Old version assigned 0 to camss->genpd_num on that board, while the new one sets it to 1 as a result of of_count_phandle_with_args(). When it is set to 1, it causes issues somewhere later in the code, the stack traces points to sysfs: Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000 Mem abort info: ESR = 0x0000000096000006 EC = 0x25: DABT (current EL), IL = 32 bits SET = 0, FnV = 0 EA = 0, S1PTW = 0 FSC = 0x06: level 2 translation fault Data abort info: ISV = 0, ISS = 0x00000006 CM = 0, WnR = 0 user pgtable: 4k pages, 48-bit VAs, pgdp=0000000080fba000 [0000000000000000] pgd=0800000080fd7003, p4d=0800000080fd7003, pud=0800000080fdb003, pmd=0000000000000000 Internal error: Oops: 96000006 [#2] PREEMPT SMP Modules linked in: crct10dif_ce asix(+) qcom_wcnss_pil socinfo adv7511 snd_soc_msm8916_digital snd_soc_lpass_apq8016 snd_soc_lpass_cpu snd_soc_lpass_platform snd_soc_apq8016_sbc snd_soc_qcom_common qrtr qcom_q6v5_mss qcom_pil_info qcom_q6v5 qcom_sysmon qcom_common qcom_glink_smem qmi_helpers snd_soc_msm8916_analog qcom_camss qnoc_msm8916 icc_smd_rpm videobuf2_dma_sg v4l2_fwnode qcom_spmi_temp_alarm v4l2_async rtc_pm8xxx videobuf2_memops venus_core qcom_pon v4l2_mem2mem videobuf2_v4l2 qcom_spmi_vadc qcom_vadc_common videobuf2_common qcom_rng qcom_stats msm videodev i2c_qcom_cci mc mdt_loader gpu_sched drm_dp_aux_bus display_connector rmtfs_mem CPU: 0 PID: 255 Comm: systemd-udevd Tainted: G D W 5.19.0-rc2-next-20220616 #12197 Hardware name: Qualcomm Technologies, Inc. APQ 8016 SBC (DT) pstate: 00000005 (nzcv daif -PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : sysfs_kf_seq_show+0x34/0x140 lr : sysfs_kf_seq_show+0x30/0x140 ng swap..[ 23.849418] sp : ffff80000c643bc0 ... Call trace: sysfs_kf_seq_show+0x34/0x140 kernfs_seq_show+0x28/0x30 seq_read_iter+0x118/0x440 kernfs_fop_read_iter+0x11c/0x1b0 new_sync_read+0xd0/0x188 vfs_read+0x134/0x1d0 ksys_read+0x64/0xf0 __arm64_sys_read+0x14/0x20 invoke_syscall+0x40/0xf8 el0_svc_common.constprop.3+0x8c/0x120 do_el0_svc_compat+0x18/0x48 el0_svc_compat+0x48/0xd0 el0t_32_sync_handler+0xec/0x140 el0t_32_sync+0x160/0x164 Code: f9401821 f9404437 97fffe37 aa0003f5 (f9400000) ---[ end trace 0000000000000000 ]--- > --- > drivers/media/platform/qcom/camss/camss.c | 38 +++++++++++++---------- > drivers/media/platform/qcom/camss/camss.h | 7 ++--- > 2 files changed, 24 insertions(+), 21 deletions(-) > > diff --git a/drivers/media/platform/qcom/camss/camss.c b/drivers/media/platform/qcom/camss/camss.c > index 79ad82e233cb..32d72b4f947b 100644 > --- a/drivers/media/platform/qcom/camss/camss.c > +++ b/drivers/media/platform/qcom/camss/camss.c > @@ -1452,19 +1452,31 @@ static const struct media_device_ops camss_media_ops = { > > static int camss_configure_pd(struct camss *camss) > { > - int nbr_pm_domains = 0; > + struct device *dev = camss->dev; > int last_pm_domain = 0; > int i; > int ret; > > - if (camss->version == CAMSS_8x96 || > - camss->version == CAMSS_660) > - nbr_pm_domains = PM_DOMAIN_GEN1_COUNT; > - else if (camss->version == CAMSS_845 || > - camss->version == CAMSS_8250) > - nbr_pm_domains = PM_DOMAIN_GEN2_COUNT; > + camss->genpd_num = of_count_phandle_with_args(dev->of_node, > + "power-domains", > + "#power-domain-cells"); > + if (camss->genpd_num < 0) { > + dev_err(dev, "Power domains are not defined for camss\n"); > + return camss->genpd_num; > + } > + > + camss->genpd = devm_kmalloc_array(dev, camss->genpd_num, > + sizeof(*camss->genpd), GFP_KERNEL); > + if (!camss->genpd) > + return -ENOMEM; > > - for (i = 0; i < nbr_pm_domains; i++) { > + camss->genpd_link = devm_kmalloc_array(dev, camss->genpd_num, > + sizeof(*camss->genpd_link), > + GFP_KERNEL); > + if (!camss->genpd_link) > + return -ENOMEM; > + > + for (i = 0; i < camss->genpd_num; i++) { > camss->genpd[i] = dev_pm_domain_attach_by_id(camss->dev, i); > if (IS_ERR(camss->genpd[i])) { > ret = PTR_ERR(camss->genpd[i]); > @@ -1689,7 +1701,6 @@ static int camss_probe(struct platform_device *pdev) > > void camss_delete(struct camss *camss) > { > - int nbr_pm_domains = 0; > int i; > > v4l2_device_unregister(&camss->v4l2_dev); > @@ -1698,14 +1709,7 @@ void camss_delete(struct camss *camss) > > pm_runtime_disable(camss->dev); > > - if (camss->version == CAMSS_8x96 || > - camss->version == CAMSS_660) > - nbr_pm_domains = PM_DOMAIN_GEN1_COUNT; > - else if (camss->version == CAMSS_845 || > - camss->version == CAMSS_8250) > - nbr_pm_domains = PM_DOMAIN_GEN2_COUNT; > - > - for (i = 0; i < nbr_pm_domains; i++) { > + for (i = 0; i < camss->genpd_num; i++) { > device_link_del(camss->genpd_link[i]); > dev_pm_domain_detach(camss->genpd[i], true); > } > diff --git a/drivers/media/platform/qcom/camss/camss.h b/drivers/media/platform/qcom/camss/camss.h > index c9b3e0df5be8..0db80cadbbaa 100644 > --- a/drivers/media/platform/qcom/camss/camss.h > +++ b/drivers/media/platform/qcom/camss/camss.h > @@ -69,9 +69,7 @@ struct resources_icc { > enum pm_domain { > PM_DOMAIN_VFE0 = 0, > PM_DOMAIN_VFE1 = 1, > - PM_DOMAIN_GEN1_COUNT = 2, /* CAMSS series of ISPs */ > PM_DOMAIN_VFELITE = 2, /* VFELITE / TOP GDSC */ > - PM_DOMAIN_GEN2_COUNT = 3, /* Titan series of ISPs */ > }; > > enum camss_version { > @@ -101,8 +99,9 @@ struct camss { > int vfe_num; > struct vfe_device *vfe; > atomic_t ref_count; > - struct device *genpd[PM_DOMAIN_GEN2_COUNT]; > - struct device_link *genpd_link[PM_DOMAIN_GEN2_COUNT]; > + int genpd_num; > + struct device **genpd; > + struct device_link **genpd_link; > struct icc_path *icc_path[ICC_SM8250_COUNT]; > struct icc_bw_tbl icc_bw_tbl[ICC_SM8250_COUNT]; > }; Best regards -- Marek Szyprowski, PhD Samsung R&D Institute Poland