linux-clk.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [bug report] clk: scmi: Allocate CLK operations dynamically
@ 2024-02-20 10:13 Dan Carpenter
  2024-02-20 11:09 ` Cristian Marussi
  0 siblings, 1 reply; 2+ messages in thread
From: Dan Carpenter @ 2024-02-20 10:13 UTC (permalink / raw)
  To: cristian.marussi; +Cc: linux-clk

Hello Cristian Marussi,

The patch 11f5b1a48a70: "clk: scmi: Allocate CLK operations
dynamically" from Feb 14, 2024 (linux-next), leads to the following
Smatch static checker warning:

	drivers/clk/clk-scmi.c:362 scmi_clocks_probe()
	error: uninitialized symbol 'atomic_threshold'.

drivers/clk/clk-scmi.c
    307 static int scmi_clocks_probe(struct scmi_device *sdev)
    308 {
    309         int idx, count, err;
    310         unsigned int atomic_threshold;
    311         bool is_atomic;
    312         struct clk_hw **hws;
    313         struct clk_hw_onecell_data *clk_data;
    314         struct device *dev = &sdev->dev;
    315         struct device_node *np = dev->of_node;
    316         const struct scmi_handle *handle = sdev->handle;
    317         struct scmi_protocol_handle *ph;
    318 
    319         if (!handle)
    320                 return -ENODEV;
    321 
    322         scmi_proto_clk_ops =
    323                 handle->devm_protocol_get(sdev, SCMI_PROTOCOL_CLOCK, &ph);
    324         if (IS_ERR(scmi_proto_clk_ops))
    325                 return PTR_ERR(scmi_proto_clk_ops);
    326 
    327         count = scmi_proto_clk_ops->count_get(ph);
    328         if (count < 0) {
    329                 dev_err(dev, "%pOFn: invalid clock output count\n", np);
    330                 return -EINVAL;
    331         }
    332 
    333         clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count),
    334                                 GFP_KERNEL);
    335         if (!clk_data)
    336                 return -ENOMEM;
    337 
    338         clk_data->num = count;
    339         hws = clk_data->hws;
    340 
    341         is_atomic = handle->is_transport_atomic(handle, &atomic_threshold);

atomic_threshold is not initialized when is_atomic is false.

    342 
    343         for (idx = 0; idx < count; idx++) {
    344                 struct scmi_clk *sclk;
    345                 const struct clk_ops *scmi_ops;
    346 
    347                 sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
    348                 if (!sclk)
    349                         return -ENOMEM;
    350 
    351                 sclk->info = scmi_proto_clk_ops->info_get(ph, idx);
    352                 if (!sclk->info) {
    353                         dev_dbg(dev, "invalid clock info for idx %d\n", idx);
    354                         devm_kfree(dev, sclk);
    355                         continue;
    356                 }
    357 
    358                 sclk->id = idx;
    359                 sclk->ph = ph;
    360                 sclk->dev = dev;
    361 
--> 362                 scmi_ops = scmi_clk_ops_alloc(sclk, is_atomic, atomic_threshold);
                                                            ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
Here we're passing uninitialized data, but it's only used when
is_atomic is true.  This is okay if scmi_clk_ops_alloc() is inlined,
but it is considered a bug when it's not inlined.

    363                 if (!scmi_ops)
    364                         return -ENOMEM;
    365 
    366                 /* Initialize clock parent data. */
    367                 if (sclk->info->num_parents > 0) {
    368                         sclk->parent_data = devm_kcalloc(dev, sclk->info->num_parents,
    369                                                          sizeof(*sclk->parent_data), GFP_KERNEL);
    370                         if (!sclk->parent_data)
    371                                 return -ENOMEM;
    372 
    373                         for (int i = 0; i < sclk->info->num_parents; i++) {
    374                                 sclk->parent_data[i].index = sclk->info->parents[i];
    375                                 sclk->parent_data[i].hw = hws[sclk->info->parents[i]];
    376                         }
    377                 }
    378 
    379                 err = scmi_clk_ops_init(dev, sclk, scmi_ops);
    380                 if (err) {
    381                         dev_err(dev, "failed to register clock %d\n", idx);
    382                         devm_kfree(dev, sclk->parent_data);
    383                         devm_kfree(dev, scmi_ops);
    384                         devm_kfree(dev, sclk);
    385                         hws[idx] = NULL;
    386                 } else {
    387                         dev_dbg(dev, "Registered clock:%s%s\n",
    388                                 sclk->info->name,
    389                                 scmi_ops->enable ? " (atomic ops)" : "");
    390                         hws[idx] = &sclk->hw;
    391                 }
    392         }
    393 
    394         return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
    395                                            clk_data);
    396 }

regards,
dan carpenter

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [bug report] clk: scmi: Allocate CLK operations dynamically
  2024-02-20 10:13 [bug report] clk: scmi: Allocate CLK operations dynamically Dan Carpenter
@ 2024-02-20 11:09 ` Cristian Marussi
  0 siblings, 0 replies; 2+ messages in thread
From: Cristian Marussi @ 2024-02-20 11:09 UTC (permalink / raw)
  To: Dan Carpenter; +Cc: linux-clk

On Tue, Feb 20, 2024 at 01:13:21PM +0300, Dan Carpenter wrote:
> Hello Cristian Marussi,
> 
Hi,

> The patch 11f5b1a48a70: "clk: scmi: Allocate CLK operations
> dynamically" from Feb 14, 2024 (linux-next), leads to the following
> Smatch static checker warning:
> 
> 	drivers/clk/clk-scmi.c:362 scmi_clocks_probe()
> 	error: uninitialized symbol 'atomic_threshold'.
> 
> drivers/clk/clk-scmi.c
>     307 static int scmi_clocks_probe(struct scmi_device *sdev)
>     308 {
>     309         int idx, count, err;
>     310         unsigned int atomic_threshold;
>     311         bool is_atomic;
>     312         struct clk_hw **hws;
>     313         struct clk_hw_onecell_data *clk_data;
>     314         struct device *dev = &sdev->dev;
>     315         struct device_node *np = dev->of_node;
>     316         const struct scmi_handle *handle = sdev->handle;
>     317         struct scmi_protocol_handle *ph;
>     318 
>     319         if (!handle)
>     320                 return -ENODEV;
>     321 
>     322         scmi_proto_clk_ops =
>     323                 handle->devm_protocol_get(sdev, SCMI_PROTOCOL_CLOCK, &ph);
>     324         if (IS_ERR(scmi_proto_clk_ops))
>     325                 return PTR_ERR(scmi_proto_clk_ops);
>     326 
>     327         count = scmi_proto_clk_ops->count_get(ph);
>     328         if (count < 0) {
>     329                 dev_err(dev, "%pOFn: invalid clock output count\n", np);
>     330                 return -EINVAL;
>     331         }
>     332 
>     333         clk_data = devm_kzalloc(dev, struct_size(clk_data, hws, count),
>     334                                 GFP_KERNEL);
>     335         if (!clk_data)
>     336                 return -ENOMEM;
>     337 
>     338         clk_data->num = count;
>     339         hws = clk_data->hws;
>     340 
>     341         is_atomic = handle->is_transport_atomic(handle, &atomic_threshold);
> 
> atomic_threshold is not initialized when is_atomic is false.
>

yes

>     342 
>     343         for (idx = 0; idx < count; idx++) {
>     344                 struct scmi_clk *sclk;
>     345                 const struct clk_ops *scmi_ops;
>     346 
>     347                 sclk = devm_kzalloc(dev, sizeof(*sclk), GFP_KERNEL);
>     348                 if (!sclk)
>     349                         return -ENOMEM;
>     350 
>     351                 sclk->info = scmi_proto_clk_ops->info_get(ph, idx);
>     352                 if (!sclk->info) {
>     353                         dev_dbg(dev, "invalid clock info for idx %d\n", idx);
>     354                         devm_kfree(dev, sclk);
>     355                         continue;
>     356                 }
>     357 
>     358                 sclk->id = idx;
>     359                 sclk->ph = ph;
>     360                 sclk->dev = dev;
>     361 
> --> 362                 scmi_ops = scmi_clk_ops_alloc(sclk, is_atomic, atomic_threshold);
>                                                             ^^^^^^^^^^ ^^^^^^^^^^^^^^^^
> Here we're passing uninitialized data, but it's only used when
> is_atomic is true.  This is okay if scmi_clk_ops_alloc() is inlined,
> but it is considered a bug when it's not inlined.
>

Ok, I will add an explicit initialization to mute smatch but why is it
this considered a bug only when not inlined, because it cannot verify
that it is indeed not used when uninitialized ?

Thanks,
Cristian

>     363                 if (!scmi_ops)
>     364                         return -ENOMEM;
>     365 
>     366                 /* Initialize clock parent data. */
>     367                 if (sclk->info->num_parents > 0) {
>     368                         sclk->parent_data = devm_kcalloc(dev, sclk->info->num_parents,
>     369                                                          sizeof(*sclk->parent_data), GFP_KERNEL);
>     370                         if (!sclk->parent_data)
>     371                                 return -ENOMEM;
>     372 
>     373                         for (int i = 0; i < sclk->info->num_parents; i++) {
>     374                                 sclk->parent_data[i].index = sclk->info->parents[i];
>     375                                 sclk->parent_data[i].hw = hws[sclk->info->parents[i]];
>     376                         }
>     377                 }
>     378 
>     379                 err = scmi_clk_ops_init(dev, sclk, scmi_ops);
>     380                 if (err) {
>     381                         dev_err(dev, "failed to register clock %d\n", idx);
>     382                         devm_kfree(dev, sclk->parent_data);
>     383                         devm_kfree(dev, scmi_ops);
>     384                         devm_kfree(dev, sclk);
>     385                         hws[idx] = NULL;
>     386                 } else {
>     387                         dev_dbg(dev, "Registered clock:%s%s\n",
>     388                                 sclk->info->name,
>     389                                 scmi_ops->enable ? " (atomic ops)" : "");
>     390                         hws[idx] = &sclk->hw;
>     391                 }
>     392         }
>     393 
>     394         return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
>     395                                            clk_data);
>     396 }
> 
> regards,
> dan carpenter

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2024-02-20 11:09 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-02-20 10:13 [bug report] clk: scmi: Allocate CLK operations dynamically Dan Carpenter
2024-02-20 11:09 ` Cristian Marussi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).