summaryrefslogtreecommitdiff
path: root/include/linux
diff options
context:
space:
mode:
authorJerome Brunet <jbrunet@baylibre.com>2026-07-23 15:00:51 +0200
committerBrian Masney <bmasney@redhat.com>2026-09-01 07:12:49 -0400
commita1c8d531c694e193dc48ef2428877d5ea2e35134 (patch)
treec01b135d4a4a12e886aeb7687b822629cbfa0abb /include/linux
parent4fbb1d7c25b01369d656662933171ed7ff74f71c (diff)
downloadlinux-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.h22
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,