blob: f1d6776ef405d85e508b225a027e064ac5f07928 [file] [log] [blame]
/* Copyright (c) 2013-2014, 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_dependency_graph.h"
#include "ipa_rm_i.h"
static int ipa_rm_dep_get_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);
return resource_index;
}
/**
* ipa_rm_dep_graph_create() - creates graph
* @dep_graph: [out] created dependency graph
*
* Returns: dependency graph on success, NULL on failure
*/
int ipa_rm_dep_graph_create(struct ipa_rm_dep_graph **dep_graph)
{
int result = 0;
*dep_graph = kzalloc(sizeof(**dep_graph), GFP_KERNEL);
if (!*dep_graph) {
IPA_RM_ERR("no mem\n");
result = -ENOMEM;
goto bail;
}
bail:
return result;
}
/**
* ipa_rm_dep_graph_delete() - destroyes the graph
* @graph: [in] dependency graph
*
* Frees all resources.
*/
void ipa_rm_dep_graph_delete(struct ipa_rm_dep_graph *graph)
{
int resource_index;
if (!graph) {
IPA_RM_ERR("invalid params\n");
return;
}
for (resource_index = 0;
resource_index < IPA_RM_RESOURCE_MAX;
resource_index++)
kfree(graph->resource_table[resource_index]);
memset(graph->resource_table, 0, sizeof(graph->resource_table));
}
/**
* ipa_rm_dep_graph_get_resource() - provides a resource by name
* @graph: [in] dependency graph
* @name: [in] name of the resource
* @resource: [out] resource in case of success
*
* Returns: 0 on success, negative on failure
*/
int ipa_rm_dep_graph_get_resource(
struct ipa_rm_dep_graph *graph,
enum ipa_rm_resource_name resource_name,
struct ipa_rm_resource **resource)
{
int result;
int resource_index;
if (!graph) {
result = -EINVAL;
goto bail;
}
resource_index = ipa_rm_dep_get_index(resource_name);
if (resource_index == IPA_RM_INDEX_INVALID) {
result = -EINVAL;
goto bail;
}
*resource = graph->resource_table[resource_index];
if (!*resource) {
result = -EINVAL;
goto bail;
}
result = 0;
bail:
return result;
}
/**
* ipa_rm_dep_graph_add() - adds resource to graph
* @graph: [in] dependency graph
* @resource: [in] resource to add
*
* Returns: 0 on success, negative on failure
*/
int ipa_rm_dep_graph_add(struct ipa_rm_dep_graph *graph,
struct ipa_rm_resource *resource)
{
int result = 0;
int resource_index;
if (!graph || !resource) {
result = -EINVAL;
goto bail;
}
resource_index = ipa_rm_dep_get_index(resource->name);
if (resource_index == IPA_RM_INDEX_INVALID) {
result = -EINVAL;
goto bail;
}
graph->resource_table[resource_index] = resource;
bail:
return result;
}
/**
* ipa_rm_dep_graph_remove() - removes resource from graph
* @graph: [in] dependency graph
* @resource: [in] resource to add
*
* Returns: 0 on success, negative on failure
*/
int ipa_rm_dep_graph_remove(struct ipa_rm_dep_graph *graph,
enum ipa_rm_resource_name resource_name)
{
if (!graph)
return -EINVAL;
graph->resource_table[resource_name] = NULL;
return 0;
}
/**
* ipa_rm_dep_graph_add_dependency() - adds dependency between
* two nodes in graph
* @graph: [in] dependency graph
* @resource_name: [in] resource to add
* @depends_on_name: [in] resource to add
*
* Returns: 0 on success, negative on failure
*/
int ipa_rm_dep_graph_add_dependency(struct ipa_rm_dep_graph *graph,
enum ipa_rm_resource_name resource_name,
enum ipa_rm_resource_name depends_on_name)
{
struct ipa_rm_resource *dependant = NULL;
struct ipa_rm_resource *dependency = NULL;
int result;
if (!graph ||
!IPA_RM_RESORCE_IS_PROD(resource_name) ||
!IPA_RM_RESORCE_IS_CONS(depends_on_name)) {
IPA_RM_ERR("invalid params\n");
result = -EINVAL;
goto bail;
}
if (ipa_rm_dep_graph_get_resource(graph,
resource_name,
&dependant)) {
IPA_RM_ERR("%s does not exist\n",
ipa_rm_resource_str(resource_name));
result = -EINVAL;
goto bail;
}
if (ipa_rm_dep_graph_get_resource(graph,
depends_on_name,
&dependency)) {
IPA_RM_ERR("%s does not exist\n",
ipa_rm_resource_str(depends_on_name));
result = -EINVAL;
goto bail;
}
result = ipa_rm_resource_add_dependency(dependant, dependency);
bail:
IPA_RM_DBG("EXIT with %d\n", result);
return result;
}
/**
* ipa_rm_dep_graph_delete_dependency() - deleted dependency between
* two nodes in graph
* @graph: [in] dependency graph
* @resource_name: [in] resource to delete
* @depends_on_name: [in] resource to delete
*
* Returns: 0 on success, negative on failure
*
*/
int ipa_rm_dep_graph_delete_dependency(struct ipa_rm_dep_graph *graph,
enum ipa_rm_resource_name resource_name,
enum ipa_rm_resource_name depends_on_name)
{
struct ipa_rm_resource *dependant = NULL;
struct ipa_rm_resource *dependency = NULL;
int result;
if (!graph ||
!IPA_RM_RESORCE_IS_PROD(resource_name) ||
!IPA_RM_RESORCE_IS_CONS(depends_on_name)) {
IPA_RM_ERR("invalid params\n");
result = -EINVAL;
goto bail;
}
if (ipa_rm_dep_graph_get_resource(graph,
resource_name,
&dependant)) {
IPA_RM_ERR("%s does not exist\n",
ipa_rm_resource_str(resource_name));
result = -EINVAL;
goto bail;
}
if (ipa_rm_dep_graph_get_resource(graph,
depends_on_name,
&dependency)) {
IPA_RM_ERR("%s does not exist\n",
ipa_rm_resource_str(depends_on_name));
result = -EINVAL;
goto bail;
}
result = ipa_rm_resource_delete_dependency(dependant, dependency);
bail:
IPA_RM_DBG("EXIT with %d\n", result);
return result;
}