summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorhselasky <hselasky@FreeBSD.org>2016-05-23 12:03:40 +0000
committerhselasky <hselasky@FreeBSD.org>2016-05-23 12:03:40 +0000
commit704290bfa2b697b24d77e129af0ff7c804aaedca (patch)
treeb3a9924afa6f050c0c897138c7432e08f1a8d1de
parent024c1d0e21075d1388cb9d72e892c74a2edadbc4 (diff)
downloadFreeBSD-src-704290bfa2b697b24d77e129af0ff7c804aaedca.zip
FreeBSD-src-704290bfa2b697b24d77e129af0ff7c804aaedca.tar.gz
Add more list_xxx() functions to the LinuxKPI.
Obtained from: kmacy @ MFC after: 1 week Sponsored by: Mellanox Technologies
-rw-r--r--sys/compat/linuxkpi/common/include/linux/list.h19
-rw-r--r--sys/compat/linuxkpi/common/src/linux_compat.c42
2 files changed, 61 insertions, 0 deletions
diff --git a/sys/compat/linuxkpi/common/include/linux/list.h b/sys/compat/linuxkpi/common/include/linux/list.h
index 1357555..fff5243 100644
--- a/sys/compat/linuxkpi/common/include/linux/list.h
+++ b/sys/compat/linuxkpi/common/include/linux/list.h
@@ -109,6 +109,13 @@ list_replace(struct list_head *old, struct list_head *new)
}
static inline void
+list_replace_init(struct list_head *old, struct list_head *new)
+{
+ list_replace(old, new);
+ INIT_LIST_HEAD(old);
+}
+
+static inline void
linux_list_add(struct list_head *new, struct list_head *prev,
struct list_head *next)
{
@@ -132,9 +139,18 @@ list_del_init(struct list_head *entry)
#define list_first_entry(ptr, type, member) \
list_entry((ptr)->next, type, member)
+#define list_last_entry(ptr, type, member) \
+ list_entry((ptr)->prev, type, member)
+
+#define list_first_entry_or_null(ptr, type, member) \
+ (!list_empty(ptr) ? list_first_entry(ptr, type, member) : NULL)
+
#define list_next_entry(ptr, member) \
list_entry(((ptr)->member.next), typeof(*(ptr)), member)
+#define list_prev_entry(ptr, member) \
+ list_entry(((ptr)->member.prev), typeof(*(ptr)), member)
+
#define list_for_each(p, head) \
for (p = (head)->next; p != (head); p = (p)->next)
@@ -436,4 +452,7 @@ static inline int list_is_last(const struct list_head *list,
(pos) && ({ n = (pos)->member.next; 1; }); \
pos = hlist_entry_safe(n, typeof(*(pos)), member))
+extern void list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv,
+ struct list_head *a, struct list_head *b));
+
#endif /* _LINUX_LIST_H_ */
diff --git a/sys/compat/linuxkpi/common/src/linux_compat.c b/sys/compat/linuxkpi/common/src/linux_compat.c
index 77b18a3..670ffc0 100644
--- a/sys/compat/linuxkpi/common/src/linux_compat.c
+++ b/sys/compat/linuxkpi/common/src/linux_compat.c
@@ -72,6 +72,7 @@ __FBSDID("$FreeBSD$");
#include <linux/interrupt.h>
#include <linux/uaccess.h>
#include <linux/kernel.h>
+#include <linux/list.h>
#include <vm/vm_pager.h>
@@ -1358,6 +1359,47 @@ unregister_inetaddr_notifier(struct notifier_block *nb)
return (0);
}
+struct list_sort_thunk {
+ int (*cmp)(void *, struct list_head *, struct list_head *);
+ void *priv;
+};
+
+static inline int
+linux_le_cmp(void *priv, const void *d1, const void *d2)
+{
+ struct list_head *le1, *le2;
+ struct list_sort_thunk *thunk;
+
+ thunk = priv;
+ le1 = *(__DECONST(struct list_head **, d1));
+ le2 = *(__DECONST(struct list_head **, d2));
+ return ((thunk->cmp)(thunk->priv, le1, le2));
+}
+
+void
+list_sort(void *priv, struct list_head *head, int (*cmp)(void *priv,
+ struct list_head *a, struct list_head *b))
+{
+ struct list_sort_thunk thunk;
+ struct list_head **ar, *le;
+ size_t count, i;
+
+ count = 0;
+ list_for_each(le, head)
+ count++;
+ ar = malloc(sizeof(struct list_head *) * count, M_KMALLOC, M_WAITOK);
+ i = 0;
+ list_for_each(le, head)
+ ar[i++] = le;
+ thunk.cmp = cmp;
+ thunk.priv = priv;
+ qsort_r(ar, count, sizeof(struct list_head *), &thunk, linux_le_cmp);
+ INIT_LIST_HEAD(head);
+ for (i = 0; i < count; i++)
+ list_add_tail(ar[i], head);
+ free(ar, M_KMALLOC);
+}
+
void
linux_irq_handler(void *ent)
{
OpenPOWER on IntegriCloud