18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * lib/parman.c - Manager for linear priority array areas
38c2ecf20Sopenharmony_ci * Copyright (c) 2017 Mellanox Technologies. All rights reserved.
48c2ecf20Sopenharmony_ci * Copyright (c) 2017 Jiri Pirko <jiri@mellanox.com>
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
78c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions are met:
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
108c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer.
118c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce the above copyright
128c2ecf20Sopenharmony_ci *    notice, this list of conditions and the following disclaimer in the
138c2ecf20Sopenharmony_ci *    documentation and/or other materials provided with the distribution.
148c2ecf20Sopenharmony_ci * 3. Neither the names of the copyright holders nor the names of its
158c2ecf20Sopenharmony_ci *    contributors may be used to endorse or promote products derived from
168c2ecf20Sopenharmony_ci *    this software without specific prior written permission.
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the
198c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free
208c2ecf20Sopenharmony_ci * Software Foundation.
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
238c2ecf20Sopenharmony_ci * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
248c2ecf20Sopenharmony_ci * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
258c2ecf20Sopenharmony_ci * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
268c2ecf20Sopenharmony_ci * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
278c2ecf20Sopenharmony_ci * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
288c2ecf20Sopenharmony_ci * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
298c2ecf20Sopenharmony_ci * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
308c2ecf20Sopenharmony_ci * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
318c2ecf20Sopenharmony_ci * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
328c2ecf20Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGE.
338c2ecf20Sopenharmony_ci */
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include <linux/kernel.h>
368c2ecf20Sopenharmony_ci#include <linux/module.h>
378c2ecf20Sopenharmony_ci#include <linux/slab.h>
388c2ecf20Sopenharmony_ci#include <linux/export.h>
398c2ecf20Sopenharmony_ci#include <linux/list.h>
408c2ecf20Sopenharmony_ci#include <linux/err.h>
418c2ecf20Sopenharmony_ci#include <linux/parman.h>
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_cistruct parman_algo {
448c2ecf20Sopenharmony_ci	int (*item_add)(struct parman *parman, struct parman_prio *prio,
458c2ecf20Sopenharmony_ci			struct parman_item *item);
468c2ecf20Sopenharmony_ci	void (*item_remove)(struct parman *parman, struct parman_prio *prio,
478c2ecf20Sopenharmony_ci			    struct parman_item *item);
488c2ecf20Sopenharmony_ci};
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_cistruct parman {
518c2ecf20Sopenharmony_ci	const struct parman_ops *ops;
528c2ecf20Sopenharmony_ci	void *priv;
538c2ecf20Sopenharmony_ci	const struct parman_algo *algo;
548c2ecf20Sopenharmony_ci	unsigned long count;
558c2ecf20Sopenharmony_ci	unsigned long limit_count;
568c2ecf20Sopenharmony_ci	struct list_head prio_list;
578c2ecf20Sopenharmony_ci};
588c2ecf20Sopenharmony_ci
598c2ecf20Sopenharmony_cistatic int parman_enlarge(struct parman *parman)
608c2ecf20Sopenharmony_ci{
618c2ecf20Sopenharmony_ci	unsigned long new_count = parman->limit_count +
628c2ecf20Sopenharmony_ci				  parman->ops->resize_step;
638c2ecf20Sopenharmony_ci	int err;
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci	err = parman->ops->resize(parman->priv, new_count);
668c2ecf20Sopenharmony_ci	if (err)
678c2ecf20Sopenharmony_ci		return err;
688c2ecf20Sopenharmony_ci	parman->limit_count = new_count;
698c2ecf20Sopenharmony_ci	return 0;
708c2ecf20Sopenharmony_ci}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_cistatic int parman_shrink(struct parman *parman)
738c2ecf20Sopenharmony_ci{
748c2ecf20Sopenharmony_ci	unsigned long new_count = parman->limit_count -
758c2ecf20Sopenharmony_ci				  parman->ops->resize_step;
768c2ecf20Sopenharmony_ci	int err;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	if (new_count < parman->ops->base_count)
798c2ecf20Sopenharmony_ci		return 0;
808c2ecf20Sopenharmony_ci	err = parman->ops->resize(parman->priv, new_count);
818c2ecf20Sopenharmony_ci	if (err)
828c2ecf20Sopenharmony_ci		return err;
838c2ecf20Sopenharmony_ci	parman->limit_count = new_count;
848c2ecf20Sopenharmony_ci	return 0;
858c2ecf20Sopenharmony_ci}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_cistatic bool parman_prio_used(struct parman_prio *prio)
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_ci{
908c2ecf20Sopenharmony_ci	return !list_empty(&prio->item_list);
918c2ecf20Sopenharmony_ci}
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_cistatic struct parman_item *parman_prio_first_item(struct parman_prio *prio)
948c2ecf20Sopenharmony_ci{
958c2ecf20Sopenharmony_ci	return list_first_entry(&prio->item_list,
968c2ecf20Sopenharmony_ci				typeof(struct parman_item), list);
978c2ecf20Sopenharmony_ci}
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_cistatic unsigned long parman_prio_first_index(struct parman_prio *prio)
1008c2ecf20Sopenharmony_ci{
1018c2ecf20Sopenharmony_ci	return parman_prio_first_item(prio)->index;
1028c2ecf20Sopenharmony_ci}
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_cistatic struct parman_item *parman_prio_last_item(struct parman_prio *prio)
1058c2ecf20Sopenharmony_ci{
1068c2ecf20Sopenharmony_ci	return list_last_entry(&prio->item_list,
1078c2ecf20Sopenharmony_ci			       typeof(struct parman_item), list);
1088c2ecf20Sopenharmony_ci}
1098c2ecf20Sopenharmony_ci
1108c2ecf20Sopenharmony_cistatic unsigned long parman_prio_last_index(struct parman_prio *prio)
1118c2ecf20Sopenharmony_ci{
1128c2ecf20Sopenharmony_ci	return parman_prio_last_item(prio)->index;
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic unsigned long parman_lsort_new_index_find(struct parman *parman,
1168c2ecf20Sopenharmony_ci						 struct parman_prio *prio)
1178c2ecf20Sopenharmony_ci{
1188c2ecf20Sopenharmony_ci	list_for_each_entry_from_reverse(prio, &parman->prio_list, list) {
1198c2ecf20Sopenharmony_ci		if (!parman_prio_used(prio))
1208c2ecf20Sopenharmony_ci			continue;
1218c2ecf20Sopenharmony_ci		return parman_prio_last_index(prio) + 1;
1228c2ecf20Sopenharmony_ci	}
1238c2ecf20Sopenharmony_ci	return 0;
1248c2ecf20Sopenharmony_ci}
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_cistatic void __parman_prio_move(struct parman *parman, struct parman_prio *prio,
1278c2ecf20Sopenharmony_ci			       struct parman_item *item, unsigned long to_index,
1288c2ecf20Sopenharmony_ci			       unsigned long count)
1298c2ecf20Sopenharmony_ci{
1308c2ecf20Sopenharmony_ci	parman->ops->move(parman->priv, item->index, to_index, count);
1318c2ecf20Sopenharmony_ci}
1328c2ecf20Sopenharmony_ci
1338c2ecf20Sopenharmony_cistatic void parman_prio_shift_down(struct parman *parman,
1348c2ecf20Sopenharmony_ci				   struct parman_prio *prio)
1358c2ecf20Sopenharmony_ci{
1368c2ecf20Sopenharmony_ci	struct parman_item *item;
1378c2ecf20Sopenharmony_ci	unsigned long to_index;
1388c2ecf20Sopenharmony_ci
1398c2ecf20Sopenharmony_ci	if (!parman_prio_used(prio))
1408c2ecf20Sopenharmony_ci		return;
1418c2ecf20Sopenharmony_ci	item = parman_prio_first_item(prio);
1428c2ecf20Sopenharmony_ci	to_index = parman_prio_last_index(prio) + 1;
1438c2ecf20Sopenharmony_ci	__parman_prio_move(parman, prio, item, to_index, 1);
1448c2ecf20Sopenharmony_ci	list_move_tail(&item->list, &prio->item_list);
1458c2ecf20Sopenharmony_ci	item->index = to_index;
1468c2ecf20Sopenharmony_ci}
1478c2ecf20Sopenharmony_ci
1488c2ecf20Sopenharmony_cistatic void parman_prio_shift_up(struct parman *parman,
1498c2ecf20Sopenharmony_ci				 struct parman_prio *prio)
1508c2ecf20Sopenharmony_ci{
1518c2ecf20Sopenharmony_ci	struct parman_item *item;
1528c2ecf20Sopenharmony_ci	unsigned long to_index;
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	if (!parman_prio_used(prio))
1558c2ecf20Sopenharmony_ci		return;
1568c2ecf20Sopenharmony_ci	item = parman_prio_last_item(prio);
1578c2ecf20Sopenharmony_ci	to_index = parman_prio_first_index(prio) - 1;
1588c2ecf20Sopenharmony_ci	__parman_prio_move(parman, prio, item, to_index, 1);
1598c2ecf20Sopenharmony_ci	list_move(&item->list, &prio->item_list);
1608c2ecf20Sopenharmony_ci	item->index = to_index;
1618c2ecf20Sopenharmony_ci}
1628c2ecf20Sopenharmony_ci
1638c2ecf20Sopenharmony_cistatic void parman_prio_item_remove(struct parman *parman,
1648c2ecf20Sopenharmony_ci				    struct parman_prio *prio,
1658c2ecf20Sopenharmony_ci				    struct parman_item *item)
1668c2ecf20Sopenharmony_ci{
1678c2ecf20Sopenharmony_ci	struct parman_item *last_item;
1688c2ecf20Sopenharmony_ci	unsigned long to_index;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	last_item = parman_prio_last_item(prio);
1718c2ecf20Sopenharmony_ci	if (last_item == item) {
1728c2ecf20Sopenharmony_ci		list_del(&item->list);
1738c2ecf20Sopenharmony_ci		return;
1748c2ecf20Sopenharmony_ci	}
1758c2ecf20Sopenharmony_ci	to_index = item->index;
1768c2ecf20Sopenharmony_ci	__parman_prio_move(parman, prio, last_item, to_index, 1);
1778c2ecf20Sopenharmony_ci	list_del(&last_item->list);
1788c2ecf20Sopenharmony_ci	list_replace(&item->list, &last_item->list);
1798c2ecf20Sopenharmony_ci	last_item->index = to_index;
1808c2ecf20Sopenharmony_ci}
1818c2ecf20Sopenharmony_ci
1828c2ecf20Sopenharmony_cistatic int parman_lsort_item_add(struct parman *parman,
1838c2ecf20Sopenharmony_ci				 struct parman_prio *prio,
1848c2ecf20Sopenharmony_ci				 struct parman_item *item)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	struct parman_prio *prio2;
1878c2ecf20Sopenharmony_ci	unsigned long new_index;
1888c2ecf20Sopenharmony_ci	int err;
1898c2ecf20Sopenharmony_ci
1908c2ecf20Sopenharmony_ci	if (parman->count + 1 > parman->limit_count) {
1918c2ecf20Sopenharmony_ci		err = parman_enlarge(parman);
1928c2ecf20Sopenharmony_ci		if (err)
1938c2ecf20Sopenharmony_ci			return err;
1948c2ecf20Sopenharmony_ci	}
1958c2ecf20Sopenharmony_ci
1968c2ecf20Sopenharmony_ci	new_index = parman_lsort_new_index_find(parman, prio);
1978c2ecf20Sopenharmony_ci	list_for_each_entry_reverse(prio2, &parman->prio_list, list) {
1988c2ecf20Sopenharmony_ci		if (prio2 == prio)
1998c2ecf20Sopenharmony_ci			break;
2008c2ecf20Sopenharmony_ci		parman_prio_shift_down(parman, prio2);
2018c2ecf20Sopenharmony_ci	}
2028c2ecf20Sopenharmony_ci	item->index = new_index;
2038c2ecf20Sopenharmony_ci	list_add_tail(&item->list, &prio->item_list);
2048c2ecf20Sopenharmony_ci	parman->count++;
2058c2ecf20Sopenharmony_ci	return 0;
2068c2ecf20Sopenharmony_ci}
2078c2ecf20Sopenharmony_ci
2088c2ecf20Sopenharmony_cistatic void parman_lsort_item_remove(struct parman *parman,
2098c2ecf20Sopenharmony_ci				     struct parman_prio *prio,
2108c2ecf20Sopenharmony_ci				     struct parman_item *item)
2118c2ecf20Sopenharmony_ci{
2128c2ecf20Sopenharmony_ci	parman_prio_item_remove(parman, prio, item);
2138c2ecf20Sopenharmony_ci	list_for_each_entry_continue(prio, &parman->prio_list, list)
2148c2ecf20Sopenharmony_ci		parman_prio_shift_up(parman, prio);
2158c2ecf20Sopenharmony_ci	parman->count--;
2168c2ecf20Sopenharmony_ci	if (parman->limit_count - parman->count >= parman->ops->resize_step)
2178c2ecf20Sopenharmony_ci		parman_shrink(parman);
2188c2ecf20Sopenharmony_ci}
2198c2ecf20Sopenharmony_ci
2208c2ecf20Sopenharmony_cistatic const struct parman_algo parman_lsort = {
2218c2ecf20Sopenharmony_ci	.item_add	= parman_lsort_item_add,
2228c2ecf20Sopenharmony_ci	.item_remove	= parman_lsort_item_remove,
2238c2ecf20Sopenharmony_ci};
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_cistatic const struct parman_algo *parman_algos[] = {
2268c2ecf20Sopenharmony_ci	&parman_lsort,
2278c2ecf20Sopenharmony_ci};
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci/**
2308c2ecf20Sopenharmony_ci * parman_create - creates a new parman instance
2318c2ecf20Sopenharmony_ci * @ops:	caller-specific callbacks
2328c2ecf20Sopenharmony_ci * @priv:	pointer to a private data passed to the ops
2338c2ecf20Sopenharmony_ci *
2348c2ecf20Sopenharmony_ci * Note: all locking must be provided by the caller.
2358c2ecf20Sopenharmony_ci *
2368c2ecf20Sopenharmony_ci * Each parman instance manages an array area with chunks of entries
2378c2ecf20Sopenharmony_ci * with the same priority. Consider following example:
2388c2ecf20Sopenharmony_ci *
2398c2ecf20Sopenharmony_ci * item 1 with prio 10
2408c2ecf20Sopenharmony_ci * item 2 with prio 10
2418c2ecf20Sopenharmony_ci * item 3 with prio 10
2428c2ecf20Sopenharmony_ci * item 4 with prio 20
2438c2ecf20Sopenharmony_ci * item 5 with prio 20
2448c2ecf20Sopenharmony_ci * item 6 with prio 30
2458c2ecf20Sopenharmony_ci * item 7 with prio 30
2468c2ecf20Sopenharmony_ci * item 8 with prio 30
2478c2ecf20Sopenharmony_ci *
2488c2ecf20Sopenharmony_ci * In this example, there are 3 priority chunks. The order of the priorities
2498c2ecf20Sopenharmony_ci * matters, however the order of items within a single priority chunk does not
2508c2ecf20Sopenharmony_ci * matter. So the same array could be ordered as follows:
2518c2ecf20Sopenharmony_ci *
2528c2ecf20Sopenharmony_ci * item 2 with prio 10
2538c2ecf20Sopenharmony_ci * item 3 with prio 10
2548c2ecf20Sopenharmony_ci * item 1 with prio 10
2558c2ecf20Sopenharmony_ci * item 5 with prio 20
2568c2ecf20Sopenharmony_ci * item 4 with prio 20
2578c2ecf20Sopenharmony_ci * item 7 with prio 30
2588c2ecf20Sopenharmony_ci * item 8 with prio 30
2598c2ecf20Sopenharmony_ci * item 6 with prio 30
2608c2ecf20Sopenharmony_ci *
2618c2ecf20Sopenharmony_ci * The goal of parman is to maintain the priority ordering. The caller
2628c2ecf20Sopenharmony_ci * provides @ops with callbacks parman uses to move the items
2638c2ecf20Sopenharmony_ci * and resize the array area.
2648c2ecf20Sopenharmony_ci *
2658c2ecf20Sopenharmony_ci * Returns a pointer to newly created parman instance in case of success,
2668c2ecf20Sopenharmony_ci * otherwise it returns NULL.
2678c2ecf20Sopenharmony_ci */
2688c2ecf20Sopenharmony_cistruct parman *parman_create(const struct parman_ops *ops, void *priv)
2698c2ecf20Sopenharmony_ci{
2708c2ecf20Sopenharmony_ci	struct parman *parman;
2718c2ecf20Sopenharmony_ci
2728c2ecf20Sopenharmony_ci	parman = kzalloc(sizeof(*parman), GFP_KERNEL);
2738c2ecf20Sopenharmony_ci	if (!parman)
2748c2ecf20Sopenharmony_ci		return NULL;
2758c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&parman->prio_list);
2768c2ecf20Sopenharmony_ci	parman->ops = ops;
2778c2ecf20Sopenharmony_ci	parman->priv = priv;
2788c2ecf20Sopenharmony_ci	parman->limit_count = ops->base_count;
2798c2ecf20Sopenharmony_ci	parman->algo = parman_algos[ops->algo];
2808c2ecf20Sopenharmony_ci	return parman;
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parman_create);
2838c2ecf20Sopenharmony_ci
2848c2ecf20Sopenharmony_ci/**
2858c2ecf20Sopenharmony_ci * parman_destroy - destroys existing parman instance
2868c2ecf20Sopenharmony_ci * @parman:	parman instance
2878c2ecf20Sopenharmony_ci *
2888c2ecf20Sopenharmony_ci * Note: all locking must be provided by the caller.
2898c2ecf20Sopenharmony_ci */
2908c2ecf20Sopenharmony_civoid parman_destroy(struct parman *parman)
2918c2ecf20Sopenharmony_ci{
2928c2ecf20Sopenharmony_ci	WARN_ON(!list_empty(&parman->prio_list));
2938c2ecf20Sopenharmony_ci	kfree(parman);
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parman_destroy);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci/**
2988c2ecf20Sopenharmony_ci * parman_prio_init - initializes a parman priority chunk
2998c2ecf20Sopenharmony_ci * @parman:	parman instance
3008c2ecf20Sopenharmony_ci * @prio:	parman prio structure to be initialized
3018c2ecf20Sopenharmony_ci * @prority:	desired priority of the chunk
3028c2ecf20Sopenharmony_ci *
3038c2ecf20Sopenharmony_ci * Note: all locking must be provided by the caller.
3048c2ecf20Sopenharmony_ci *
3058c2ecf20Sopenharmony_ci * Before caller could add an item with certain priority, he has to
3068c2ecf20Sopenharmony_ci * initialize a priority chunk for it using this function.
3078c2ecf20Sopenharmony_ci */
3088c2ecf20Sopenharmony_civoid parman_prio_init(struct parman *parman, struct parman_prio *prio,
3098c2ecf20Sopenharmony_ci		      unsigned long priority)
3108c2ecf20Sopenharmony_ci{
3118c2ecf20Sopenharmony_ci	struct parman_prio *prio2;
3128c2ecf20Sopenharmony_ci	struct list_head *pos;
3138c2ecf20Sopenharmony_ci
3148c2ecf20Sopenharmony_ci	INIT_LIST_HEAD(&prio->item_list);
3158c2ecf20Sopenharmony_ci	prio->priority = priority;
3168c2ecf20Sopenharmony_ci
3178c2ecf20Sopenharmony_ci	/* Position inside the list according to priority */
3188c2ecf20Sopenharmony_ci	list_for_each(pos, &parman->prio_list) {
3198c2ecf20Sopenharmony_ci		prio2 = list_entry(pos, typeof(*prio2), list);
3208c2ecf20Sopenharmony_ci		if (prio2->priority > prio->priority)
3218c2ecf20Sopenharmony_ci			break;
3228c2ecf20Sopenharmony_ci	}
3238c2ecf20Sopenharmony_ci	list_add_tail(&prio->list, pos);
3248c2ecf20Sopenharmony_ci}
3258c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parman_prio_init);
3268c2ecf20Sopenharmony_ci
3278c2ecf20Sopenharmony_ci/**
3288c2ecf20Sopenharmony_ci * parman_prio_fini - finalizes use of parman priority chunk
3298c2ecf20Sopenharmony_ci * @prio:	parman prio structure
3308c2ecf20Sopenharmony_ci *
3318c2ecf20Sopenharmony_ci * Note: all locking must be provided by the caller.
3328c2ecf20Sopenharmony_ci */
3338c2ecf20Sopenharmony_civoid parman_prio_fini(struct parman_prio *prio)
3348c2ecf20Sopenharmony_ci{
3358c2ecf20Sopenharmony_ci	WARN_ON(parman_prio_used(prio));
3368c2ecf20Sopenharmony_ci	list_del(&prio->list);
3378c2ecf20Sopenharmony_ci}
3388c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parman_prio_fini);
3398c2ecf20Sopenharmony_ci
3408c2ecf20Sopenharmony_ci/**
3418c2ecf20Sopenharmony_ci * parman_item_add - adds a parman item under defined priority
3428c2ecf20Sopenharmony_ci * @parman:	parman instance
3438c2ecf20Sopenharmony_ci * @prio:	parman prio instance to add the item to
3448c2ecf20Sopenharmony_ci * @item:	parman item instance
3458c2ecf20Sopenharmony_ci *
3468c2ecf20Sopenharmony_ci * Note: all locking must be provided by the caller.
3478c2ecf20Sopenharmony_ci *
3488c2ecf20Sopenharmony_ci * Adds item to a array managed by parman instance under the specified priority.
3498c2ecf20Sopenharmony_ci *
3508c2ecf20Sopenharmony_ci * Returns 0 in case of success, negative number to indicate an error.
3518c2ecf20Sopenharmony_ci */
3528c2ecf20Sopenharmony_ciint parman_item_add(struct parman *parman, struct parman_prio *prio,
3538c2ecf20Sopenharmony_ci		    struct parman_item *item)
3548c2ecf20Sopenharmony_ci{
3558c2ecf20Sopenharmony_ci	return parman->algo->item_add(parman, prio, item);
3568c2ecf20Sopenharmony_ci}
3578c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parman_item_add);
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci/**
3608c2ecf20Sopenharmony_ci * parman_item_del - deletes parman item
3618c2ecf20Sopenharmony_ci * @parman:	parman instance
3628c2ecf20Sopenharmony_ci * @prio:	parman prio instance to delete the item from
3638c2ecf20Sopenharmony_ci * @item:	parman item instance
3648c2ecf20Sopenharmony_ci *
3658c2ecf20Sopenharmony_ci * Note: all locking must be provided by the caller.
3668c2ecf20Sopenharmony_ci */
3678c2ecf20Sopenharmony_civoid parman_item_remove(struct parman *parman, struct parman_prio *prio,
3688c2ecf20Sopenharmony_ci			struct parman_item *item)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	parman->algo->item_remove(parman, prio, item);
3718c2ecf20Sopenharmony_ci}
3728c2ecf20Sopenharmony_ciEXPORT_SYMBOL(parman_item_remove);
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
3758c2ecf20Sopenharmony_ciMODULE_AUTHOR("Jiri Pirko <jiri@mellanox.com>");
3768c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Priority-based array manager");
377