summaryrefslogtreecommitdiff
path: root/include/linux/kref.h
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-04-21 11:21:59 -0600
committerTom Rini <[email protected]>2026-04-21 11:21:59 -0600
commit052988aa29bfd506d7ce207fbb3f5374a5dbecbb (patch)
tree7eae9dc76b1383368733804f5e2801faaaa481a8 /include/linux/kref.h
parent5d401bfbdf1da9eb34575b0b15e18757f2b38ca0 (diff)
parentf1f4a1d1d8355b0fc6bfc82d9ca6741a8e92623b (diff)
Merge patch series "Linux compat improvements and CCF prep"
Casey Connolly <[email protected]> says: This series implements various improvements to Linux header compatibility, largely in preparation for a full port of Linux CCF but many of these changes would also be helpful when porting other drivers. Beside the basic header/compat stuff there are a few larger patches: Patch 1 adds the "%pOF" format specifier to vsprintf, this behaves the same as it does in Linux printing the name of the ofnode, but notably it expects an ofnode pointer rather than a device_node. Patch 2 adds an option to skip doing a full DM scan pre-relocation. Some platforms like Qualcomm don't actually need devices to be probed prior to relocation, it is also quite slow to scan the entire FDT before caches are up. This option gets us to main loop 30-50% faster. Unfortunately it isn't possible to totally skip DM since U-Boot will panic if it can't find a serial port, but the serial uclass code will bind the serial port itself by reading /chosen/stdout-path, however any dependencies like clocks won't be found so this should only be enabled if the serial driver gracefully handles missing clocks. Patch 3 adds [k]strdup_const(), this works the same as the Linux version saving a small amount of memory by avoiding duplicating strings stored in .rodata, this is particularly useful for CCF. Patch 4 adds 64-bit versions of some 32-bit ofnode utilities functions, making it possible to parse 64-bit arrays. Patch 6 provides a simple implementation of kref, this will be used by CCF. Patch 9 adds devm_krealloc() support to devres, it relies on storing allocation sizes in the devres struct which will add a small overhead. Link: https://lore.kernel.org/r/[email protected]
Diffstat (limited to 'include/linux/kref.h')
-rw-r--r--include/linux/kref.h124
1 files changed, 124 insertions, 0 deletions
diff --git a/include/linux/kref.h b/include/linux/kref.h
new file mode 100644
index 00000000000..30927047d54
--- /dev/null
+++ b/include/linux/kref.h
@@ -0,0 +1,124 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * kref.h - library routines for handling generic reference counted objects
+ *
+ * Copyright (C) 2004 Greg Kroah-Hartman <[email protected]>
+ * Copyright (C) 2004 IBM Corp.
+ *
+ * based on kobject.h which was:
+ * Copyright (C) 2002-2003 Patrick Mochel <[email protected]>
+ * Copyright (C) 2002-2003 Open Source Development Labs
+ */
+
+#ifndef _KREF_H_
+#define _KREF_H_
+
+#include <linux/compat.h>
+
+struct kref {
+ long refcount;
+};
+
+#define KREF_INIT(n) { .refcount = REFCOUNT_INIT(n), }
+
+/**
+ * kref_init - initialize object.
+ * @kref: object in question.
+ */
+static inline void kref_init(struct kref *kref)
+{
+ kref->refcount = 1;
+}
+
+static inline unsigned int kref_read(const struct kref *kref)
+{
+ return kref->refcount;
+}
+
+/**
+ * kref_get - increment refcount for object.
+ * @kref: object.
+ */
+static inline void kref_get(struct kref *kref)
+{
+ kref->refcount++;
+}
+
+/**
+ * kref_put - Decrement refcount for object
+ * @kref: Object
+ * @release: Pointer to the function that will clean up the object when the
+ * last reference to the object is released.
+ *
+ * Decrement the refcount, and if 0, call @release. The caller may not
+ * pass NULL or kfree() as the release function.
+ *
+ * Return: 1 if this call removed the object, otherwise return 0. Beware,
+ * if this function returns 0, another caller may have removed the object
+ * by the time this function returns. The return value is only certain
+ * if you want to see if the object is definitely released.
+ */
+static inline int kref_put(struct kref *kref, void (*release)(struct kref *kref))
+{
+ if (--kref->refcount == 0) {
+ release(kref);
+ return 1;
+ }
+ return 0;
+}
+
+/**
+ * kref_put_mutex - Decrement refcount for object
+ * @kref: Object
+ * @release: Pointer to the function that will clean up the object when the
+ * last reference to the object is released.
+ * @mutex: Mutex which protects the release function.
+ *
+ * This variant of kref_lock() calls the @release function with the @mutex
+ * held. The @release function will release the mutex.
+ */
+static inline int kref_put_mutex(struct kref *kref,
+ void (*release)(struct kref *kref),
+ struct mutex *mutex)
+{
+ return kref_put(kref, release);
+}
+
+/**
+ * kref_put_lock - Decrement refcount for object
+ * @kref: Object
+ * @release: Pointer to the function that will clean up the object when the
+ * last reference to the object is released.
+ * @lock: Spinlock which protects the release function.
+ *
+ * This variant of kref_lock() calls the @release function with the @lock
+ * held. The @release function will release the lock.
+ */
+static inline int kref_put_lock(struct kref *kref,
+ void (*release)(struct kref *kref),
+ spinlock_t *lock)
+{
+ return kref_put(kref, release);
+}
+
+/**
+ * kref_get_unless_zero - Increment refcount for object unless it is zero.
+ * @kref: object.
+ *
+ * This function is intended to simplify locking around refcounting for
+ * objects that can be looked up from a lookup structure, and which are
+ * removed from that lookup structure in the object destructor.
+ * Operations on such objects require at least a read lock around
+ * lookup + kref_get, and a write lock around kref_put + remove from lookup
+ * structure. Furthermore, RCU implementations become extremely tricky.
+ * With a lookup followed by a kref_get_unless_zero *with return value check*
+ * locking in the kref_put path can be deferred to the actual removal from
+ * the lookup structure and RCU lookups become trivial.
+ *
+ * Return: non-zero if the increment succeeded. Otherwise return 0.
+ */
+static inline int kref_get_unless_zero(struct kref *kref)
+{
+ return kref->refcount ? kref->refcount++ : 0;
+}
+#endif /* _KREF_H_ */