blob: a44b6aa5a2435e9ade9207097a9d1b9ffacd2721 [file] [log] [blame]
/*
* Copyright (c) 2014-2018 The Linux Foundation. All rights reserved.
*
* Permission to use, copy, modify, and/or distribute this software for
* any purpose with or without fee is hereby granted, provided that the
* above copyright notice and this permission notice appear in all
* copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
* AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
* DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
* PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
* TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
* PERFORMANCE OF THIS SOFTWARE.
*/
/**
* DOC: qdf_list.c
*
* QCA driver framework list manipulation APIs. QDF linked list
* APIs are NOT thread safe so make sure to use appropriate locking mechanisms
* to assure operations on the list are thread safe.
*/
/* Include files */
#include <qdf_list.h>
#include <qdf_module.h>
/* Function declarations and documenation */
QDF_STATUS qdf_list_insert_before(qdf_list_t *list,
qdf_list_node_t *new_node, qdf_list_node_t *node)
{
list_add_tail(new_node, node);
list->count++;
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(qdf_list_insert_before);
QDF_STATUS qdf_list_insert_after(qdf_list_t *list,
qdf_list_node_t *new_node, qdf_list_node_t *node)
{
list_add(new_node, node);
list->count++;
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(qdf_list_insert_after);
/**
* qdf_list_insert_front() - insert input node at front of the list
* @list: Pointer to list
* @node: Pointer to input node
*
* Return: QDF status
*/
QDF_STATUS qdf_list_insert_front(qdf_list_t *list, qdf_list_node_t *node)
{
list_add(node, &list->anchor);
list->count++;
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(qdf_list_insert_front);
/**
* qdf_list_insert_back() - insert input node at back of the list
* @list: Pointer to list
* @node: Pointer to input node
*
* Return: QDF status
*/
QDF_STATUS qdf_list_insert_back(qdf_list_t *list, qdf_list_node_t *node)
{
list_add_tail(node, &list->anchor);
list->count++;
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(qdf_list_insert_back);
/**
* qdf_list_insert_back_size() - insert input node at back of list and save
* list size
* @list: Pointer to list
* @node: Pointer to input node
* @p_size: Pointer to store list size
*
* Return: QDF status
*/
QDF_STATUS qdf_list_insert_back_size(qdf_list_t *list,
qdf_list_node_t *node, uint32_t *p_size)
{
list_add_tail(node, &list->anchor);
list->count++;
*p_size = list->count;
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(qdf_list_insert_back_size);
/**
* qdf_list_remove_front() - remove node from front of the list
* @list: Pointer to list
* @node2: Double pointer to store the node which is removed from list
*
* Return: QDF status
*/
QDF_STATUS qdf_list_remove_front(qdf_list_t *list, qdf_list_node_t **node2)
{
struct list_head *listptr;
if (list_empty(&list->anchor))
return QDF_STATUS_E_EMPTY;
listptr = list->anchor.next;
*node2 = listptr;
list_del(list->anchor.next);
list->count--;
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(qdf_list_remove_front);
/**
* qdf_list_remove_back() - remove node from end of the list
* @list: Pointer to list
* @node2: Double pointer to store node which is removed from list
*
* Return: QDF status
*/
QDF_STATUS qdf_list_remove_back(qdf_list_t *list, qdf_list_node_t **node2)
{
struct list_head *listptr;
if (list_empty(&list->anchor))
return QDF_STATUS_E_EMPTY;
listptr = list->anchor.prev;
*node2 = listptr;
list_del(list->anchor.prev);
list->count--;
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(qdf_list_remove_back);
/**
* qdf_list_has_node() - check if a node is in a list
* @list: pointer to the list being searched
* @node: pointer to the node to search for
*
* It is expected that the list being checked is locked
* when this function is being called.
*
* Return: true if the node is in the list
*/
bool qdf_list_has_node(qdf_list_t *list, qdf_list_node_t *node)
{
qdf_list_node_t *tmp;
list_for_each(tmp, &list->anchor) {
if (tmp == node)
return true;
}
return false;
}
/**
* qdf_list_remove_node() - remove input node from list
* @list: Pointer to list
* @node_to_remove: Pointer to node which needs to be removed
*
* verifies that the node is in the list before removing it.
* It is expected that the list being removed from is locked
* when this function is being called.
*
* Return: QDF status
*/
QDF_STATUS qdf_list_remove_node(qdf_list_t *list,
qdf_list_node_t *node_to_remove)
{
if (list_empty(&list->anchor))
return QDF_STATUS_E_EMPTY;
list_del(node_to_remove);
list->count--;
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(qdf_list_remove_node);
/**
* qdf_list_peek_front() - peek front node from list
* @list: Pointer to list
* @node2: Double pointer to store peeked node pointer
*
* Return: QDF status
*/
QDF_STATUS qdf_list_peek_front(qdf_list_t *list, qdf_list_node_t **node2)
{
struct list_head *listptr;
if (list_empty(&list->anchor))
return QDF_STATUS_E_EMPTY;
listptr = list->anchor.next;
*node2 = listptr;
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(qdf_list_peek_front);
/**
* qdf_list_peek_next() - peek next node of input node in the list
* @list: Pointer to list
* @node: Pointer to input node
* @node2: Double pointer to store peeked node pointer
*
* Return: QDF status
*/
QDF_STATUS qdf_list_peek_next(qdf_list_t *list,
qdf_list_node_t *node,
qdf_list_node_t **node2)
{
if (!list || !node || !node2)
return QDF_STATUS_E_FAULT;
if (list_empty(&list->anchor))
return QDF_STATUS_E_EMPTY;
if (node->next == &list->anchor)
return QDF_STATUS_E_EMPTY;
*node2 = node->next;
return QDF_STATUS_SUCCESS;
}
qdf_export_symbol(qdf_list_peek_next);
/**
* qdf_list_empty() - check if the list is empty
* @list: pointer to the list
*
* Return: true if the list is empty and false otherwise.
*/
bool qdf_list_empty(qdf_list_t *list)
{
return list_empty(&list->anchor);
}
qdf_export_symbol(qdf_list_empty);