blob: fe8e781c4db0602bbd726f9a38fc23206fc1e85e [file] [log] [blame]
/* Copyright (c) 2013-2016, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include <linux/slab.h>
#include "ipa_rm_i.h"
/**
* ipa_rm_peers_list_get_resource_index() - resource name to index
* of this resource in corresponding peers list
* @resource_name: [in] resource name
*
* Returns: resource index mapping, IPA_RM_INDEX_INVALID
* in case provided resource name isn't contained in enum
* ipa_rm_resource_name.
*
*/
static int ipa_rm_peers_list_get_resource_index(
enum ipa_rm_resource_name resource_name)
{
int resource_index = IPA_RM_INDEX_INVALID;
if (IPA_RM_RESORCE_IS_PROD(resource_name))
resource_index = ipa_rm_prod_index(resource_name);
else if (IPA_RM_RESORCE_IS_CONS(resource_name)) {
resource_index = ipa_rm_cons_index(resource_name);
if (resource_index != IPA_RM_INDEX_INVALID)
resource_index =
resource_index - IPA_RM_RESOURCE_PROD_MAX;
}
return resource_index;
}
static bool ipa_rm_peers_list_check_index(int index,
struct ipa_rm_peers_list *peers_list)
{
return !(index > peers_list->max_peers || index < 0);
}
/**
* ipa_rm_peers_list_create() - creates the peers list
*
* @max_peers: maximum number of peers in new list
* @peers_list: [out] newly created peers list
*
* Returns: 0 in case of SUCCESS, negative otherwise
*/
int ipa_rm_peers_list_create(int max_peers,
struct ipa_rm_peers_list **peers_list)
{
int result;
*peers_list = kzalloc(sizeof(**peers_list), GFP_ATOMIC);
if (!*peers_list) {
IPA_RM_ERR("no mem\n");
result = -ENOMEM;
goto bail;
}
(*peers_list)->max_peers = max_peers;
(*peers_list)->peers = kzalloc((*peers_list)->max_peers *
sizeof(*((*peers_list)->peers)), GFP_ATOMIC);
if (!((*peers_list)->peers)) {
IPA_RM_ERR("no mem\n");
result = -ENOMEM;
goto list_alloc_fail;
}
return 0;
list_alloc_fail:
kfree(*peers_list);
bail:
return result;
}
/**
* ipa_rm_peers_list_delete() - deletes the peers list
*
* @peers_list: peers list
*
*/
void ipa_rm_peers_list_delete(struct ipa_rm_peers_list *peers_list)
{
if (peers_list) {
kfree(peers_list->peers);
kfree(peers_list);
}
}
/**
* ipa_rm_peers_list_remove_peer() - removes peer from the list
*
* @peers_list: peers list
* @resource_name: name of the resource to remove
*
*/
void ipa_rm_peers_list_remove_peer(
struct ipa_rm_peers_list *peers_list,
enum ipa_rm_resource_name resource_name)
{
if (!peers_list)
return;
peers_list->peers[ipa_rm_peers_list_get_resource_index(
resource_name)].resource = NULL;
peers_list->peers[ipa_rm_peers_list_get_resource_index(
resource_name)].userspace_dep = false;
peers_list->peers_count--;
}
/**
* ipa_rm_peers_list_add_peer() - adds peer to the list
*
* @peers_list: peers list
* @resource: resource to add
*
*/
void ipa_rm_peers_list_add_peer(
struct ipa_rm_peers_list *peers_list,
struct ipa_rm_resource *resource,
bool userspace_dep)
{
if (!peers_list || !resource)
return;
peers_list->peers[ipa_rm_peers_list_get_resource_index(
resource->name)].resource = resource;
peers_list->peers[ipa_rm_peers_list_get_resource_index(
resource->name)].userspace_dep = userspace_dep;
peers_list->peers_count++;
}
/**
* ipa_rm_peers_list_is_empty() - checks
* if resource peers list is empty
*
* @peers_list: peers list
*
* Returns: true if the list is empty, false otherwise
*/
bool ipa_rm_peers_list_is_empty(struct ipa_rm_peers_list *peers_list)
{
bool result = true;
if (!peers_list)
goto bail;
if (peers_list->peers_count > 0)
result = false;
bail:
return result;
}
/**
* ipa_rm_peers_list_has_last_peer() - checks
* if resource peers list has exactly one peer
*
* @peers_list: peers list
*
* Returns: true if the list has exactly one peer, false otherwise
*/
bool ipa_rm_peers_list_has_last_peer(
struct ipa_rm_peers_list *peers_list)
{
bool result = false;
if (!peers_list)
goto bail;
if (peers_list->peers_count == 1)
result = true;
bail:
return result;
}
/**
* ipa_rm_peers_list_check_dependency() - check dependency
* between 2 peer lists
* @resource_peers: first peers list
* @resource_name: first peers list resource name
* @depends_on_peers: second peers list
* @depends_on_name: second peers list resource name
* @userspace_dep: [out] dependency was created by userspace
*
* Returns: true if there is dependency, false otherwise
*
*/
bool ipa_rm_peers_list_check_dependency(
struct ipa_rm_peers_list *resource_peers,
enum ipa_rm_resource_name resource_name,
struct ipa_rm_peers_list *depends_on_peers,
enum ipa_rm_resource_name depends_on_name,
bool *userspace_dep)
{
bool result = false;
int resource_index;
if (!resource_peers || !depends_on_peers || !userspace_dep)
return result;
resource_index = ipa_rm_peers_list_get_resource_index(depends_on_name);
if (resource_peers->peers[resource_index].resource != NULL) {
result = true;
*userspace_dep = resource_peers->peers[resource_index].
userspace_dep;
}
resource_index = ipa_rm_peers_list_get_resource_index(resource_name);
if (depends_on_peers->peers[resource_index].resource != NULL) {
result = true;
*userspace_dep = depends_on_peers->peers[resource_index].
userspace_dep;
}
return result;
}
/**
* ipa_rm_peers_list_get_resource() - get resource by
* resource index
* @resource_index: resource index
* @resource_peers: peers list
*
* Returns: the resource if found, NULL otherwise
*/
struct ipa_rm_resource *ipa_rm_peers_list_get_resource(int resource_index,
struct ipa_rm_peers_list *resource_peers)
{
struct ipa_rm_resource *result = NULL;
if (!ipa_rm_peers_list_check_index(resource_index, resource_peers))
goto bail;
result = resource_peers->peers[resource_index].resource;
bail:
return result;
}
/**
* ipa_rm_peers_list_get_userspace_dep() - returns whether resource dependency
* was added by userspace
* @resource_index: resource index
* @resource_peers: peers list
*
* Returns: true if dependency was added by userspace, false by kernel
*/
bool ipa_rm_peers_list_get_userspace_dep(int resource_index,
struct ipa_rm_peers_list *resource_peers)
{
bool result = false;
if (!ipa_rm_peers_list_check_index(resource_index, resource_peers))
goto bail;
result = resource_peers->peers[resource_index].userspace_dep;
bail:
return result;
}
/**
* ipa_rm_peers_list_get_size() - get peers list sise
*
* @peers_list: peers list
*
* Returns: the size of the peers list
*/
int ipa_rm_peers_list_get_size(struct ipa_rm_peers_list *peers_list)
{
return peers_list->max_peers;
}