Given that decoder instance order is fundamental to the DPA translation
sequence for endpoint decoders, enforce that cxl_decoder_for_each() returns
decoders in instance order. Otherwise, they show up in readddir() order
which is not predictable.

Add a list_add_sorted() to generically handle inserting into a sorted list.

Reviewed-by: Davidlohr Bueso <d...@stgolabs.net>
Signed-off-by: Dan Williams <dan.j.willi...@intel.com>
---
 cxl/lib/libcxl.c |    8 +++++++-
 util/list.h      |   39 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 46 insertions(+), 1 deletion(-)
 create mode 100644 util/list.h

diff --git a/cxl/lib/libcxl.c b/cxl/lib/libcxl.c
index f36edcfc735a..e4c5d3819e88 100644
--- a/cxl/lib/libcxl.c
+++ b/cxl/lib/libcxl.c
@@ -19,6 +19,7 @@
 #include <ccan/short_types/short_types.h>
 
 #include <util/log.h>
+#include <util/list.h>
 #include <util/size.h>
 #include <util/sysfs.h>
 #include <util/bitmap.h>
@@ -908,6 +909,11 @@ cxl_endpoint_get_memdev(struct cxl_endpoint *endpoint)
        return NULL;
 }
 
+static int decoder_id_cmp(struct cxl_decoder *d1, struct cxl_decoder *d2)
+{
+       return d1->id - d2->id;
+}
+
 static void *add_cxl_decoder(void *parent, int id, const char *cxldecoder_base)
 {
        const char *devname = devpath_to_devname(cxldecoder_base);
@@ -1049,7 +1055,7 @@ static void *add_cxl_decoder(void *parent, int id, const 
char *cxldecoder_base)
                        return decoder_dup;
                }
 
-       list_add(&port->decoders, &decoder->list);
+       list_add_sorted(&port->decoders, decoder, list, decoder_id_cmp);
 
        free(path);
        return decoder;
diff --git a/util/list.h b/util/list.h
new file mode 100644
index 000000000000..cb7727123ea8
--- /dev/null
+++ b/util/list.h
@@ -0,0 +1,39 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (C) 2022 Intel Corporation. All rights reserved. */
+#ifndef _NDCTL_LIST_H_
+#define _NDCTL_LIST_H_
+
+#include <ccan/list/list.h>
+
+#define list_add_sorted(head, n, node, cmp)                                    
\
+       do {                                                                   \
+               struct list_head *__head = (head);                             \
+               typeof(n) __iter, __next;                                      \
+               typeof(n) __new = (n);                                         \
+                                                                               
\
+               if (list_empty(__head)) {                                      \
+                       list_add(__head, &__new->node);                        \
+                       break;                                                 \
+               }                                                              \
+                                                                               
\
+               list_for_each (__head, __iter, node) {                         \
+                       if (cmp(__new, __iter) < 0) {                          \
+                               list_add_before(__head, &__iter->node,         \
+                                               &__new->node);                 \
+                               break;                                         \
+                       }                                                      \
+                       __next = list_next(__head, __iter, node);              \
+                       if (!__next) {                                         \
+                               list_add_after(__head, &__iter->node,          \
+                                              &__new->node);                  \
+                               break;                                         \
+                       }                                                      \
+                       if (cmp(__new, __next) < 0) {                          \
+                               list_add_before(__head, &__next->node,         \
+                                               &__new->node);                 \
+                               break;                                         \
+                       }                                                      \
+               }                                                              \
+       } while (0)
+
+#endif /* _NDCTL_LIST_H_ */


Reply via email to