From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@pengutronix.de>
Subject: [PATCH v2 13/20] include: linux/idr.h: implement more Linux API
Date: Wed, 22 Nov 2023 18:29:44 +0100 [thread overview]
Message-ID: <20231122172951.376531-14-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20231122172951.376531-1-a.fatoum@pengutronix.de>
Upcoming sync of SCMI with the kernel will start using IDR API, which we
lack in barebox, so let's retrofit it.
Signed-off-by: Ahmad Fatoum <a.fatoum@pengutronix.de>
---
v1 -> v2:
- factor out longer IDR functions into separate source file
instead of header
- add IDR Kconfig symbol
- fix implementation of idr_remove, idr_destory, idr_for_each_entry
- keep IDR sorted
---
drivers/firmware/Kconfig | 1 +
drivers/firmware/arm_scmi/driver.c | 4 +-
include/linux/idr.h | 61 ++++++++----------
lib/Kconfig | 3 +
lib/Makefile | 1 +
lib/idr.c | 100 +++++++++++++++++++++++++++++
6 files changed, 133 insertions(+), 37 deletions(-)
create mode 100644 lib/idr.c
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index b4244fb1db6a..ee91b2b7fa6d 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -27,6 +27,7 @@ config ARM_SCMI_PROTOCOL
tristate "ARM System Control and Management Interface (SCMI) Message Protocol"
depends on ARM || COMPILE_TEST
depends on ARM_SMCCC
+ select IDR
help
ARM System Control and Management Interface (SCMI) protocol is a
set of operating system-independent software interfaces that are
diff --git a/drivers/firmware/arm_scmi/driver.c b/drivers/firmware/arm_scmi/driver.c
index dcd15528f394..98f672746527 100644
--- a/drivers/firmware/arm_scmi/driver.c
+++ b/drivers/firmware/arm_scmi/driver.c
@@ -988,7 +988,7 @@ static void scmi_create_protocol_devices(struct device_node *np,
*/
int scmi_protocol_device_request(const struct scmi_device_id *id_table)
{
- int ret = 0;
+ int id, ret = 0;
struct list_head *phead = NULL;
struct scmi_requested_dev *rdev;
struct scmi_info *info;
@@ -1001,7 +1001,7 @@ int scmi_protocol_device_request(const struct scmi_device_id *id_table)
* Search for the matching protocol rdev list and then search
* of any existent equally named device...fails if any duplicate found.
*/
- __idr_for_each_entry(&scmi_requested_devices, idr) {
+ idr_for_each_entry(&scmi_requested_devices, idr, id) {
struct list_head *head = idr->ptr;
if (!phead) {
/* A list found registered in the IDR is never empty */
diff --git a/include/linux/idr.h b/include/linux/idr.h
index 12494b1f01cb..9939085d0e8d 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -24,19 +24,31 @@ struct idr {
#define DEFINE_IDR(name) \
struct idr name = { .list = LIST_HEAD_INIT((name).list) }
-#define __idr_for_each_entry(head, idr) \
- list_for_each_entry((idr), &(head)->list, list)
+/**
+ * idr_for_each_entry() - Iterate over an IDR's elements of a given type.
+ * @_idr: IDR handle.
+ * @_entry: The type * to use as cursor
+ * @_id: Entry ID.
+ *
+ * @_entry and @_id do not need to be initialized before the loop, and
+ * after normal termination @_entry is left with the value NULL. This
+ * is convenient for a "not found" value.
+ */
+#define idr_for_each_entry(_idr, _entry, _id) \
+ for (struct idr *iter = \
+ list_first_entry_or_null(&(_idr)->list, struct idr, list); \
+ (iter && iter != (_idr)) || (_entry = NULL); \
+ iter = list_next_entry(iter, list)) \
+ if ((_entry = iter->ptr, _id = iter->id, true))
-static inline struct idr *__idr_find(struct idr *head, int id)
+struct idr *__idr_find(struct idr *head, int lookup_id);
+
+int idr_for_each(const struct idr *idr,
+ int (*fn)(int id, void *p, void *data), void *data);
+
+static inline int idr_is_empty(const struct idr *idr)
{
- struct idr *idr;
-
- __idr_for_each_entry(head, idr) {
- if (idr->id == id)
- return idr;
- }
-
- return NULL;
+ return list_empty(&idr->list);
}
static inline void *idr_find(struct idr *head, int id)
@@ -46,36 +58,15 @@ static inline void *idr_find(struct idr *head, int id)
return idr ? idr->ptr : NULL;
}
-static inline int idr_alloc_one(struct idr *head, void *ptr, int start)
-{
- struct idr *idr;
-
- if (__idr_find(head, start))
- return -EBUSY;
-
- idr = malloc(sizeof(*idr));
- if (!idr)
- return -ENOMEM;
-
- idr->id = start;
- idr->ptr = ptr;
-
- list_add(&idr->list, &head->list);
-
- return start;
-}
+int idr_alloc_one(struct idr *head, void *ptr, int start);
static inline void idr_init(struct idr *idr)
{
INIT_LIST_HEAD(&idr->list);
}
-static inline void idr_remove(struct idr *head, int id)
-{
- struct idr *idr = __idr_find(head, id);
+void idr_destroy(struct idr *idr);
- list_del(&idr->list);
- free(idr);
-}
+void idr_remove(struct idr *idr, int id);
#endif /* __IDR_H__ */
diff --git a/lib/Kconfig b/lib/Kconfig
index fbc9fff8654c..71715ef6e8ad 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -226,6 +226,9 @@ config GENERIC_ALLOCATOR
help
Support is curently limited to allocaing a complete mmio-sram at once.
+config IDR
+ bool
+
endmenu
source "lib/Kconfig.hardening"
diff --git a/lib/Makefile b/lib/Makefile
index 8fd950040381..38204c8273e5 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -28,6 +28,7 @@ obj-y += cmdlinepart.o
obj-y += recursive_action.o
obj-y += make_directory.o
obj-y += math.o
+obj-$(CONFIG_IDR) += idr.o
obj-y += math/
obj-y += uuid.o
obj-$(CONFIG_XXHASH) += xxhash.o
diff --git a/lib/idr.c b/lib/idr.c
new file mode 100644
index 000000000000..10a714ac03f0
--- /dev/null
+++ b/lib/idr.c
@@ -0,0 +1,100 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * 2002-10-18 written by Jim Houston jim.houston@ccur.com
+ * Copyright (C) 2002 by Concurrent Computer Corporation
+ */
+
+#include <errno.h>
+#include <linux/idr.h>
+
+struct idr *__idr_find(struct idr *head, int lookup_id)
+{
+ struct idr *cursor;
+
+ list_for_each_entry(cursor, &head->list, list) {
+ if (cursor->id == lookup_id)
+ return cursor;
+ }
+
+ return NULL;
+}
+
+/**
+ * idr_for_each() - Iterate through all stored pointers.
+ * @idr: IDR handle.
+ * @fn: Function to be called for each pointer.
+ * @data: Data passed to callback function.
+ *
+ * The callback function will be called for each entry in @idr, passing
+ * the ID, the entry and @data.
+ *
+ * If @fn returns anything other than %0, the iteration stops and that
+ * value is returned from this function.
+ */
+int idr_for_each(const struct idr *idr,
+ int (*fn)(int id, void *p, void *data), void *data)
+{
+ const struct idr *pos, *tmp;
+ int ret;
+
+ list_for_each_entry_safe(pos, tmp, &idr->list, list) {
+ ret = fn(pos->id, pos->ptr, data);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+static int idr_compare(struct list_head *a, struct list_head *b)
+{
+ int id_a = list_entry(a, struct idr, list)->id;
+ int id_b = list_entry(b, struct idr, list)->id;
+
+ return __compare3(id_a, id_b);
+}
+
+int idr_alloc_one(struct idr *head, void *ptr, int start)
+{
+ struct idr *idr;
+
+ if (__idr_find(head, start))
+ return -EBUSY;
+
+ idr = malloc(sizeof(*idr));
+ if (!idr)
+ return -ENOMEM;
+
+ idr->id = start;
+ idr->ptr = ptr;
+
+ list_add_sort(&idr->list, &head->list, idr_compare);
+
+ return start;
+}
+
+static void __idr_remove(struct idr *idr)
+{
+ list_del(&idr->list);
+ free(idr);
+}
+
+void idr_remove(struct idr *head, int id)
+{
+ struct idr *idr = __idr_find(head, id);
+ if (!idr)
+ return;
+
+ __idr_remove(idr);
+}
+
+void idr_destroy(struct idr *idr)
+{
+ struct idr *pos, *tmp;
+
+ if (!idr)
+ return;
+
+ list_for_each_entry_safe(pos, tmp, &idr->list, list)
+ __idr_remove(pos);
+}
--
2.39.2
next prev parent reply other threads:[~2023-11-22 17:42 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-22 17:29 [PATCH v2 00/20] prepare for porting OP-TEE communication support Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 01/20] include: provide linux/errno.h Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 02/20] include: add linux/refcount.h Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 03/20] bitops: split off linux/bits.h Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 04/20] include: import <linux/instruction_pointer.h> Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 05/20] asm-generic: split off typeconfused readl and friends Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 06/20] asm-generic: migrate relaxed helpers into asm-generic/io.h Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 07/20] include: add linux/io.h with strict prototypes Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 08/20] include: import Linux word-at-a-time.h Ahmad Fatoum
2023-11-23 8:16 ` [PATCH] fixup! " Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 09/20] string: implement strscpy Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 10/20] of: add CONFIG_OF for Linux compatibility Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 11/20] include: asm-generic/atomic.h: define atomic_cmpxchg Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 12/20] kbuild: build barebox for -std=gnu11 Ahmad Fatoum
2023-11-22 17:29 ` Ahmad Fatoum [this message]
2023-11-30 20:37 ` [PATCH v2 13/20] include: linux/idr.h: implement more Linux API Sascha Hauer
2023-11-22 17:29 ` [PATCH v2 14/20] test: self: add simple IDR test Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 15/20] include: implement dev_warn_once and friends Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 16/20] include: add blocking notifier aliases Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 17/20] include: add Linux ktime API Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 18/20] of: constify string pointed to by struct of_device_id::compatible Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 19/20] of: define of_devices_ensure_probed_by_compatible Ahmad Fatoum
2023-11-22 17:29 ` [PATCH v2 20/20] include: add linux/device.h wrapper around driver.h Ahmad Fatoum
2023-11-23 14:50 ` [PATCH v2 00/20] prepare for porting OP-TEE communication support Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231122172951.376531-14-a.fatoum@pengutronix.de \
--to=a.fatoum@pengutronix.de \
--cc=barebox@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox