[bug report] pmdomain: mediatek: Add support for MT8196 SCPSYS power domains

Dan Carpenter dan.carpenter at linaro.org
Mon Oct 27 00:05:01 PDT 2025


Hello AngeloGioacchino Del Regno,

Commit ead9cf65d50f ("pmdomain: mediatek: Add support for MT8196
SCPSYS power domains") from Sep 25, 2025 (linux-next), leads to the
following Smatch static checker warning:

	drivers/pmdomain/mediatek/mtk-pm-domains.c:865 scpsys_add_one_domain()
	error: we previously assumed 'pd->data' could be null (see line 840)

drivers/pmdomain/mediatek/mtk-pm-domains.c
    718 static struct
    719 generic_pm_domain *scpsys_add_one_domain(struct scpsys *scpsys, struct device_node *node)
    720 {
    721         const struct scpsys_domain_data *domain_data;
    722         const struct scpsys_hwv_domain_data *hwv_domain_data;
    723         struct scpsys_domain *pd;
    724         struct property *prop;
    725         const char *clk_name;
    726         int i, ret, num_clks;
    727         struct clk *clk;
    728         int clk_ind = 0;
    729         u32 id;
    730 
    731         ret = of_property_read_u32(node, "reg", &id);
    732         if (ret) {
    733                 dev_err(scpsys->dev, "%pOF: failed to retrieve domain id from reg: %d\n",
    734                         node, ret);
    735                 return ERR_PTR(-EINVAL);
    736         }
    737 
    738         switch (scpsys->soc_data->type) {
    739         case SCPSYS_MTCMOS_TYPE_DIRECT_CTL:
    740                 if (id >= scpsys->soc_data->num_domains) {
    741                         dev_err(scpsys->dev, "%pOF: invalid domain id %d\n", node, id);
    742                         return ERR_PTR(-EINVAL);
    743                 }
    744 
    745                 domain_data = &scpsys->soc_data->domains_data[id];
    746                 hwv_domain_data = NULL;
    747 
    748                 if (domain_data->sta_mask == 0) {
    749                         dev_err(scpsys->dev, "%pOF: undefined domain id %d\n", node, id);
    750                         return ERR_PTR(-EINVAL);
    751                 }
    752 
    753                 break;
    754         case SCPSYS_MTCMOS_TYPE_HW_VOTER:
    755                 if (id >= scpsys->soc_data->num_hwv_domains) {
    756                         dev_err(scpsys->dev, "%pOF: invalid HWV domain id %d\n", node, id);
    757                         return ERR_PTR(-EINVAL);
    758                 }
    759 
    760                 domain_data = NULL;

NULL here.

    761                 hwv_domain_data = &scpsys->soc_data->hwv_domains_data[id];
    762 
    763                 break;
    764         default:
    765                 return ERR_PTR(-EINVAL);
    766         }
    767 
    768         pd = devm_kzalloc(scpsys->dev, sizeof(*pd), GFP_KERNEL);
    769         if (!pd)
    770                 return ERR_PTR(-ENOMEM);
    771 
    772         pd->data = domain_data;
                ^^^^^^^^^^^^^^^^^^^^^^

    773         pd->hwv_data = hwv_domain_data;
    774         pd->scpsys = scpsys;
    775 
    776         if (MTK_SCPD_CAPS(pd, MTK_SCPD_DOMAIN_SUPPLY)) {
    777                 pd->supply = devm_of_regulator_get_optional(scpsys->dev, node, "domain");
    778                 if (IS_ERR(pd->supply))
    779                         return dev_err_cast_probe(scpsys->dev, pd->supply,
    780                                       "%pOF: failed to get power supply.\n",
    781                                       node);
    782         }
    783 
    784         num_clks = of_clk_get_parent_count(node);
    785         if (num_clks > 0) {
    786                 /* Calculate number of subsys_clks */
    787                 of_property_for_each_string(node, "clock-names", prop, clk_name) {
    788                         char *subsys;
    789 
    790                         subsys = strchr(clk_name, '-');
    791                         if (subsys)
    792                                 pd->num_subsys_clks++;
    793                         else
    794                                 pd->num_clks++;
    795                 }
    796 
    797                 pd->clks = devm_kcalloc(scpsys->dev, pd->num_clks, sizeof(*pd->clks), GFP_KERNEL);
    798                 if (!pd->clks)
    799                         return ERR_PTR(-ENOMEM);
    800 
    801                 pd->subsys_clks = devm_kcalloc(scpsys->dev, pd->num_subsys_clks,
    802                                                sizeof(*pd->subsys_clks), GFP_KERNEL);
    803                 if (!pd->subsys_clks)
    804                         return ERR_PTR(-ENOMEM);
    805 
    806         }
    807 
    808         for (i = 0; i < pd->num_clks; i++) {
    809                 clk = of_clk_get(node, i);
    810                 if (IS_ERR(clk)) {
    811                         ret = PTR_ERR(clk);
    812                         dev_err_probe(scpsys->dev, ret,
    813                                       "%pOF: failed to get clk at index %d\n", node, i);
    814                         goto err_put_clocks;
    815                 }
    816 
    817                 pd->clks[clk_ind++].clk = clk;
    818         }
    819 
    820         for (i = 0; i < pd->num_subsys_clks; i++) {
    821                 clk = of_clk_get(node, i + clk_ind);
    822                 if (IS_ERR(clk)) {
    823                         ret = PTR_ERR(clk);
    824                         dev_err_probe(scpsys->dev, ret,
    825                                       "%pOF: failed to get clk at index %d\n", node,
    826                                       i + clk_ind);
    827                         goto err_put_subsys_clocks;
    828                 }
    829 
    830                 pd->subsys_clks[i].clk = clk;
    831         }
    832 
    833         if (scpsys->domains[id]) {
    834                 ret = -EINVAL;
    835                 dev_err(scpsys->dev,
    836                         "power domain with id %d already exists, check your device-tree\n", id);
    837                 goto err_put_subsys_clocks;
    838         }
    839 
    840         if (pd->data && pd->data->name)
                    ^^^^^^^^
Check for NULL

    841                 pd->genpd.name = pd->data->name;
    842         else if (pd->hwv_data && pd->hwv_data->name)
    843                 pd->genpd.name = pd->hwv_data->name;
    844         else
    845                 pd->genpd.name = node->name;
    846 
    847         if (scpsys->soc_data->type == SCPSYS_MTCMOS_TYPE_DIRECT_CTL) {
    848                 pd->genpd.power_off = scpsys_power_off;
    849                 pd->genpd.power_on = scpsys_power_on;
    850         } else {
    851                 pd->genpd.power_off = scpsys_hwv_power_off;
    852                 pd->genpd.power_on = scpsys_hwv_power_on;
    853 
    854                 /* HW-Voter code can be invoked in atomic context */
    855                 pd->genpd.flags |= GENPD_FLAG_IRQ_SAFE;
    856         }
    857 
    858         /*
    859          * Initially turn on all domains to make the domains usable
    860          * with !CONFIG_PM and to get the hardware in sync with the
    861          * software.  The unused domains will be switched off during
    862          * late_init time.
    863          */
    864         if (MTK_SCPD_CAPS(pd, MTK_SCPD_KEEP_DEFAULT_OFF)) {
--> 865                 if (scpsys_domain_is_on(pd))
                                                ^^
The patch adds an unchecked dereference of pd->data in the
scpsys_domain_is_on() function.


    866                         dev_warn(scpsys->dev,
    867                                  "%pOF: A default off power domain has been ON\n", node);
    868         } else {
    869                 ret = pd->genpd.power_on(&pd->genpd);
    870                 if (ret < 0) {
    871                         dev_err(scpsys->dev, "%pOF: failed to power on domain: %d\n", node, ret);
    872                         goto err_put_subsys_clocks;
    873                 }
    874 
    875                 if (MTK_SCPD_CAPS(pd, MTK_SCPD_ALWAYS_ON))
    876                         pd->genpd.flags |= GENPD_FLAG_ALWAYS_ON;
    877         }
    878 

regards,
dan carpenter



More information about the Linux-mediatek mailing list