diff options
| author | Jerome Brunet <jbrunet@baylibre.com> | 2026-07-23 15:00:51 +0200 |
|---|---|---|
| committer | Brian Masney <bmasney@redhat.com> | 2026-09-01 07:12:49 -0400 |
| commit | a1c8d531c694e193dc48ef2428877d5ea2e35134 (patch) | |
| tree | c01b135d4a4a12e886aeb7687b822629cbfa0abb /include/linux | |
| parent | 4fbb1d7c25b01369d656662933171ed7ff74f71c (diff) | |
| download | linux-next-a1c8d531c694e193dc48ef2428877d5ea2e35134.tar.gz linux-next-a1c8d531c694e193dc48ef2428877d5ea2e35134.zip | |
clk: fix self-consuming provider module pinning
clk_hw_get_clk() lets a provider get a struct clk for one of its own
struct clk_hw.
When a struct clk is created, the module usage count of the provider
is unconditionally increased. For a self-consuming provider, this means
it pins itself and the module can never be unloaded.
Increasing the module usage count should only be done when the consumer
lives in a different module from the provider. Use THIS_MODULE to
capture caller's module and increase the module usage count accordingly.
It is OK for consumer-only APIs such as clk_get() or of_clk_get() to
pass a NULL owner. As a result, any provider module will get pinned,
same as before.
Fixes: 30d6f8c15d2c ("clk: add api to get clk consumer from clk_hw")
Signed-off-by: Jerome Brunet <jbrunet@baylibre.com>
Signed-off-by: Brian Masney <bmasney@redhat.com>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/clk-provider.h | 22 |
1 files changed, 19 insertions, 3 deletions
diff --git a/include/linux/clk-provider.h b/include/linux/clk-provider.h index dc8e161f9c2c..58902e8dfd68 100644 --- a/include/linux/clk-provider.h +++ b/include/linux/clk-provider.h @@ -50,6 +50,7 @@ struct clk; struct clk_hw; struct clk_core; struct dentry; +struct module; /** * struct clk_rate_request - Structure encoding the clk constraints that @@ -351,8 +352,9 @@ struct clk_init_data { * @core: pointer to the struct clk_core instance that points back to this * struct clk_hw instance * - * @clk: pointer to the per-user struct clk instance that can be used to call - * into the clk API + * @clk: pointer to the per-user struct clk instance. This will be removed at + * some point in the future, Please consider the field obsolete and do not use + * it. Use clk_hw_get_clk() to get a per-user struct clk from a struct clk_hw. * * @init: pointer to struct clk_init_data that contains the init data shared * with the common clock framework. This pointer will be set to NULL once @@ -1474,10 +1476,24 @@ static inline struct clk_hw *__clk_get_hw(struct clk *clk) } #endif -struct clk *clk_hw_get_clk(struct clk_hw *hw, const char *con_id); +struct clk *__clk_hw_get_clk(struct clk_hw *hw, const char *con_id, + struct module *owner); struct clk *devm_clk_hw_get_clk(struct device *dev, struct clk_hw *hw, const char *con_id); +/** + * clk_hw_get_clk - get clk consumer given a clk_hw + * @hw: clk_hw associated with the clk being consumed + * @con_id: connection ID string on device + * + * Return: new clk consumer + * This is the function to be used by providers which need + * to get a consumer clk and act on the clock element + * Calls to this function must be balanced with calls to clk_put() + */ +#define clk_hw_get_clk(hw, con_id) \ + __clk_hw_get_clk((hw), (con_id), THIS_MODULE) + unsigned int clk_hw_get_num_parents(const struct clk_hw *hw); struct clk_hw *clk_hw_get_parent(const struct clk_hw *hw); struct clk_hw *clk_hw_get_parent_by_index(const struct clk_hw *hw, |
