Ira Weiny wrote:
> On Tue, Jul 12, 2022 at 12:07:52PM -0700, Dan Williams wrote:
> > 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.
> >
> > Signed-off-by: Dan Williams <[email protected]>
> > ---
> > cxl/lib/libcxl.c | 8 ++++++-
> > util/list.h | 61
> > ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> > 2 files changed, 68 insertions(+), 1 deletion(-)
> >
> > 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
> > index 1ea9c59b9f0c..c6584e3ec725 100644
> > --- a/util/list.h
> > +++ b/util/list.h
> > @@ -37,4 +37,65 @@ static inline void list_add_after_(struct list_head *h,
> > (void)list_debug(h, abortstr);
> > }
> >
> > +/**
> > + * list_add_before - add an entry before the given node in the linked list.
> > + * @h: the list_head to add the node to
> > + * @l: the list_node before which to add to
> > + * @n: the list_node to add to the list.
> > + *
> > + * The list_node does not need to be initialized; it will be overwritten.
> > + * Example:
> > + * struct child *child = malloc(sizeof(*child));
> > + *
> > + * child->name = "geoffrey";
> > + * list_add_before(&parent->children, &child1->list, &child->list);
> > + * parent->num_children++;
> > + */
> > +#define list_add_before(h, l, n) list_add_before_(h, l, n, LIST_LOC)
> > +static inline void list_add_before_(struct list_head *h, struct list_node
> > *l,
> > + struct list_node *n, const char *abortstr)
>
> I see a list_add_before() in the latest ccan list code.[1] Should we just use
> that? The implementation is a bit different.
>
> [1] https://ccodearchive.net/info/list.html
Ah, thanks for checking. Yeah, probably time to refresh our fork to the
latest upstream baseline.
>
> > +{
> > + if (l->prev == &h->n) {
> > + /* l is the first element, this becomes a list_add */
> > + list_add(h, n);
> > + return;
> > + }
> > +
> > + n->next = l;
> > + n->prev = l->prev;
> > + l->prev->next = n;
> > + l->prev = n;
>
> Did you mean to add list_debug() here?
Looks like we get that for free with the upstream rebase.