16924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi/*
26924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi * libkmod - interface to kernel module operations
36924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi *
4e6b0e49b4ea7937a98b16f23d621244ee1a3e588Lucas De Marchi * Copyright (C) 2011-2013  ProFUSION embedded systems
56924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi *
66924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi * This library is free software; you can redistribute it and/or
76924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi * modify it under the terms of the GNU Lesser General Public
8cb451f35d9fe25ec1dee0628f8af23f022358f6bLucas De Marchi * License as published by the Free Software Foundation; either
9cb451f35d9fe25ec1dee0628f8af23f022358f6bLucas De Marchi * version 2.1 of the License, or (at your option) any later version.
106924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi *
116924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi * This library is distributed in the hope that it will be useful,
126924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi * but WITHOUT ANY WARRANTY; without even the implied warranty of
136924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
146924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi * Lesser General Public License for more details.
156924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi *
166924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi * You should have received a copy of the GNU Lesser General Public
17dea2dfee9b301da84dbb09cf510b8ebf2ef28fffLucas De Marchi * License along with this library; if not, see <http://www.gnu.org/licenses/>.
186924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi */
196924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
206924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi#include <stdlib.h>
216924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
226924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi#include "libkmod.h"
2383b855a6ed7028173e231eab0a39c929a962ddf5Lucas De Marchi#include "libkmod-internal.h"
246924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
256681951bbeb04f7b5c08e49da81a0da6f2aca2d2Lucas De Marchi/**
266681951bbeb04f7b5c08e49da81a0da6f2aca2d2Lucas De Marchi * SECTION:libkmod-list
276681951bbeb04f7b5c08e49da81a0da6f2aca2d2Lucas De Marchi * @short_description: general purpose list
286681951bbeb04f7b5c08e49da81a0da6f2aca2d2Lucas De Marchi */
296681951bbeb04f7b5c08e49da81a0da6f2aca2d2Lucas De Marchi
306924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchistatic inline struct list_node *list_node_init(struct list_node *node)
316924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi{
326924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	node->next = node;
336924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	node->prev = node;
346924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
356924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	return node;
366924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi}
376924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
386924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchistatic inline void list_node_append(struct list_node *list,
396924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi							struct list_node *node)
406924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi{
416924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	if (list == NULL) {
426924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		list_node_init(node);
436924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		return;
446924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	}
456924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
466924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	node->prev = list->prev;
476924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	list->prev->next = node;
486924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	list->prev = node;
496924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	node->next = list;
506924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi}
516924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
526924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchistatic inline struct list_node *list_node_remove(struct list_node *node)
536924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi{
546924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	if (node->prev == node || node->next == node)
556924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		return NULL;
566924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
576924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	node->prev->next = node->next;
586924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	node->next->prev = node->prev;
596924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
60e16e27f4a482540de5adc3c6f02e425c227fcf32Lucas De Marchi	return node->next;
616924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi}
626924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
6386e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchistatic inline void list_node_insert_after(struct list_node *list,
6486e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi							struct list_node *node)
6586e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi{
6686e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	if (list == NULL) {
6786e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi		list_node_init(node);
6886e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi		return;
6986e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	}
7086e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi
7186e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	node->prev = list;
7286e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	node->next = list->next;
7386e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	list->next->prev = node;
7486e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	list->next = node;
7586e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi}
7686e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi
77b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchistatic inline void list_node_insert_before(struct list_node *list,
78b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi							struct list_node *node)
79b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi{
80b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	if (list == NULL) {
81b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi		list_node_init(node);
82b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi		return;
83b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	}
84b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi
85b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	node->next = list;
86b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	node->prev = list->prev;
87b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	list->prev->next = node;
88b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	list->prev = node;
89b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi}
90b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi
911965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchistatic inline void list_node_append_list(struct list_node *list1,
921965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi							struct list_node *list2)
931965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi{
941965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	struct list_node *list1_last;
951965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi
961965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	if (list1 == NULL) {
971965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi		list_node_init(list2);
981965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi		return;
991965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	}
1001965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi
1011965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	list1->prev->next = list2;
1021965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	list2->prev->next = list1;
1031965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi
1041965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	/* cache the last, because we will lose the pointer */
1051965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	list1_last = list1->prev;
1061965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi
1071965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	list1->prev = list2->prev;
1081965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	list2->prev = list1_last;
1091965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi}
1101965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi
1111ce08a563e4ff4a9bcae7a1514f1159232a16f71Gustavo Sverzut Barbieristruct kmod_list *kmod_list_append(struct kmod_list *list, const void *data)
1126924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi{
1136924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	struct kmod_list *new;
1146924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
1156924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	new = malloc(sizeof(*new));
1166924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	if (new == NULL)
1176924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		return NULL;
1186924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
1191ce08a563e4ff4a9bcae7a1514f1159232a16f71Gustavo Sverzut Barbieri	new->data = (void *)data;
1206924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	list_node_append(list ? &list->node : NULL, &new->node);
1216924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
1226924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	return list ? list : new;
1236924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi}
1246924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
125c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchistruct kmod_list *kmod_list_insert_after(struct kmod_list *list,
126c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchi							const void *data)
12786e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi{
12886e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	struct kmod_list *new;
12986e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi
13086e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	if (list == NULL)
13186e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi		return kmod_list_append(list, data);
13286e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi
13386e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	new = malloc(sizeof(*new));
13486e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	if (new == NULL)
13586e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi		return NULL;
13686e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi
13786e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	new->data = (void *)data;
13886e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	list_node_insert_after(&list->node, &new->node);
13986e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi
14086e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi	return list;
14186e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi}
14286e878857219d3b0ffc716ec3135258a9d5523f2Lucas De Marchi
143c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchistruct kmod_list *kmod_list_insert_before(struct kmod_list *list,
144c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchi							const void *data)
145b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi{
146b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	struct kmod_list *new;
147b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi
148b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	if (list == NULL)
149b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi		return kmod_list_append(list, data);
150b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi
151b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	new = malloc(sizeof(*new));
152b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	if (new == NULL)
153b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi		return NULL;
154b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi
155b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	new->data = (void *)data;
156b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	list_node_insert_before(&list->node, &new->node);
157b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi
158b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi	return new;
159b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi}
160b91a1c6d3d4780d59a63bafd89c42c1910022b54Lucas De Marchi
1611965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchistruct kmod_list *kmod_list_append_list(struct kmod_list *list1,
1621965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi						struct kmod_list *list2)
1631965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi{
1641965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	if (list1 == NULL)
1651965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi		return list2;
1661965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi
167434f32ca8d2858568c1ef959ae3f3c24a1c9be2aLucas De Marchi	if (list2 == NULL)
168434f32ca8d2858568c1ef959ae3f3c24a1c9be2aLucas De Marchi		return list1;
169434f32ca8d2858568c1ef959ae3f3c24a1c9be2aLucas De Marchi
1701965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	list_node_append_list(&list1->node, &list2->node);
1711965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi
1721965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi	return list1;
1731965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi}
1741965029cb08ed31aca48921bd0418033cc0b060aLucas De Marchi
1751ce08a563e4ff4a9bcae7a1514f1159232a16f71Gustavo Sverzut Barbieristruct kmod_list *kmod_list_prepend(struct kmod_list *list, const void *data)
1766924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi{
1776924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	struct kmod_list *new;
1786924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
1796924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	new = malloc(sizeof(*new));
1806924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	if (new == NULL)
1816924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		return NULL;
1826924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
1831ce08a563e4ff4a9bcae7a1514f1159232a16f71Gustavo Sverzut Barbieri	new->data = (void *)data;
1846924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	list_node_append(list ? &list->node : NULL, &new->node);
1856924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
1866924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	return new;
1876924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi}
1886924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
1896924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchistruct kmod_list *kmod_list_remove(struct kmod_list *list)
1906924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi{
1916924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	struct list_node *node;
1926924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
1936924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	if (list == NULL)
1946924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		return NULL;
1956924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
1966924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	node = list_node_remove(&list->node);
1976924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	free(list);
1986924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
1996924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	if (node == NULL)
2006924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		return NULL;
2016924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
2026924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	return container_of(node, struct kmod_list, node);
2036924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi}
2046924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
2056924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchistruct kmod_list *kmod_list_remove_data(struct kmod_list *list,
2066924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi							const void *data)
2076924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi{
2086924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	struct kmod_list *itr;
2096924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	struct list_node *node;
2106924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
2116924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	for (itr = list; itr != NULL; itr = kmod_list_next(list, itr)) {
2126924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		if (itr->data == data)
2136924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi			break;
2146924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	}
2156924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
2166924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	if (itr == NULL)
2176924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		return list;
2186924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
2196924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	node = list_node_remove(&itr->node);
2206924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	free(itr);
2216924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
2226924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	if (node == NULL)
2236924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		return NULL;
2246924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
2256924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	return container_of(node, struct kmod_list, node);
2266924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi}
2276924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
22862be799554c468b483afdda36f6e9903662aab23Lucas De Marchi/*
22962be799554c468b483afdda36f6e9903662aab23Lucas De Marchi * n must be greater to or equal the number of elements (we don't check the
2307e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * condition)
23162be799554c468b483afdda36f6e9903662aab23Lucas De Marchi */
23262be799554c468b483afdda36f6e9903662aab23Lucas De Marchistruct kmod_list *kmod_list_remove_n_latest(struct kmod_list *list,
23362be799554c468b483afdda36f6e9903662aab23Lucas De Marchi							unsigned int n)
23462be799554c468b483afdda36f6e9903662aab23Lucas De Marchi{
235eb4ae531f7693c52fc42a612b99127e591575eedLucas De Marchi	struct kmod_list *l = list;
23662be799554c468b483afdda36f6e9903662aab23Lucas De Marchi	unsigned int i;
23762be799554c468b483afdda36f6e9903662aab23Lucas De Marchi
238eb4ae531f7693c52fc42a612b99127e591575eedLucas De Marchi	for (i = 0; i < n; i++) {
239eb4ae531f7693c52fc42a612b99127e591575eedLucas De Marchi		l = kmod_list_last(l);
24062be799554c468b483afdda36f6e9903662aab23Lucas De Marchi		l = kmod_list_remove(l);
241eb4ae531f7693c52fc42a612b99127e591575eedLucas De Marchi	}
24262be799554c468b483afdda36f6e9903662aab23Lucas De Marchi
243eb4ae531f7693c52fc42a612b99127e591575eedLucas De Marchi	return l;
24462be799554c468b483afdda36f6e9903662aab23Lucas De Marchi}
245eb4ae531f7693c52fc42a612b99127e591575eedLucas De Marchi
2467e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi/**
2477e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * kmod_list_prev:
2487e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * @list: the head of the list
2497e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * @curr: the current node in the list
2507e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi *
2517e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * Get the previous node in @list relative to @curr as if @list was not a
2527e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * circular list. I.e.: the previous of the head is NULL. It can be used to
2537e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * iterate a list by checking for NULL return to know when all elements were
2547e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * iterated.
2557e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi *
2567e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * Returns: node previous to @curr or NULL if either this node is the head of
2577e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * the list or the list is empty.
2587e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi */
2591ce08a563e4ff4a9bcae7a1514f1159232a16f71Gustavo Sverzut BarbieriKMOD_EXPORT struct kmod_list *kmod_list_prev(const struct kmod_list *list,
260c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchi						const struct kmod_list *curr)
26179d77111dc4026effbbd3e7b60970b0b2ac6179cLucas De Marchi{
26279d77111dc4026effbbd3e7b60970b0b2ac6179cLucas De Marchi	if (list == NULL || curr == NULL)
26379d77111dc4026effbbd3e7b60970b0b2ac6179cLucas De Marchi		return NULL;
26479d77111dc4026effbbd3e7b60970b0b2ac6179cLucas De Marchi
2652a70a5d4e0e62313a905378d463bc5857c5eef0bGustavo Sverzut Barbieri	if (list == curr)
26679d77111dc4026effbbd3e7b60970b0b2ac6179cLucas De Marchi		return NULL;
26779d77111dc4026effbbd3e7b60970b0b2ac6179cLucas De Marchi
26879d77111dc4026effbbd3e7b60970b0b2ac6179cLucas De Marchi	return container_of(curr->node.prev, struct kmod_list, node);
26979d77111dc4026effbbd3e7b60970b0b2ac6179cLucas De Marchi}
27079d77111dc4026effbbd3e7b60970b0b2ac6179cLucas De Marchi
2717e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi/**
2727e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * kmod_list_next:
2737e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * @list: the head of the list
2747e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * @curr: the current node in the list
2757e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi *
2767e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * Get the next node in @list relative to @curr as if @list was not a circular
2777e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * list. I.e. calling this function in the last node of the list returns
2787e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * NULL.. It can be used to iterate a list by checking for NULL return to know
2797e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * when all elements were iterated.
2807e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi *
2817e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * Returns: node next to @curr or NULL if either this node is the last of or
2827e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi * list is empty.
2837e1b3ae2b902031d3ec042a7f87fd3ecc98a4018Lucas De Marchi */
2841ce08a563e4ff4a9bcae7a1514f1159232a16f71Gustavo Sverzut BarbieriKMOD_EXPORT struct kmod_list *kmod_list_next(const struct kmod_list *list,
285c35347f15cf0ed71a0929ddb0a0d8e2de5f73de8Lucas De Marchi						const struct kmod_list *curr)
2866924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi{
2876924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	if (list == NULL || curr == NULL)
2886924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		return NULL;
2896924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
2906924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	if (curr->node.next == &list->node)
2916924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi		return NULL;
2926924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi
2936924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi	return container_of(curr->node.next, struct kmod_list, node);
2946924e47a8d1af9ed2d42709358802fbb43fff8d4Lucas De Marchi}
295d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri
296d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri/**
297d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri * kmod_list_last:
298d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri * @list: the head of the list
299d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri *
300d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri * Get the last element of the @list. As @list is a circular list,
301d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri * this is a cheap operation O(1) with the last element being the
302d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri * previous element.
303d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri *
304d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri * If the list has a single element it will return the list itself (as
305d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri * expected, and this is what differentiates from kmod_list_prev()).
306d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri *
307d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri * Returns: last node at @list or NULL if the list is empty.
308d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri */
309d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut BarbieriKMOD_EXPORT struct kmod_list *kmod_list_last(const struct kmod_list *list)
310d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri{
311d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri	if (list == NULL)
312d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri		return NULL;
313d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri	return container_of(list->node.prev, struct kmod_list, node);
314d5ec60bc0c2fa92a05e766463761b6e22d6d67b4Gustavo Sverzut Barbieri}
315