brintos

brintos / linux-shallow public Read only

0
0
Text · 6.7 KiB · 6d29241 Raw
307 lines · c
1/*2 * Copyright 2012-15 Advanced Micro Devices, Inc.3 *4 * Permission is hereby granted, free of charge, to any person obtaining a5 * copy of this software and associated documentation files (the "Software"),6 * to deal in the Software without restriction, including without limitation7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,8 * and/or sell copies of the Software, and to permit persons to whom the9 * Software is furnished to do so, subject to the following conditions:10 *11 * The above copyright notice and this permission notice shall be included in12 * all copies or substantial portions of the Software.13 *14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR20 * OTHER DEALINGS IN THE SOFTWARE.21 *22 * Authors: AMD23 *24 */25 26#include "dm_services.h"27#include "include/vector.h"28 29bool dal_vector_construct(30	struct vector *vector,31	struct dc_context *ctx,32	uint32_t capacity,33	uint32_t struct_size)34{35	vector->container = NULL;36 37	if (!struct_size || !capacity) {38		/* Container must be non-zero size*/39		BREAK_TO_DEBUGGER();40		return false;41	}42 43	vector->container = kcalloc(capacity, struct_size, GFP_KERNEL);44	if (vector->container == NULL)45		return false;46	vector->capacity = capacity;47	vector->struct_size = struct_size;48	vector->count = 0;49	vector->ctx = ctx;50	return true;51}52 53static bool dal_vector_presized_costruct(struct vector *vector,54					 struct dc_context *ctx,55					 uint32_t count,56					 void *initial_value,57					 uint32_t struct_size)58{59	uint32_t i;60 61	vector->container = NULL;62 63	if (!struct_size || !count) {64		/* Container must be non-zero size*/65		BREAK_TO_DEBUGGER();66		return false;67	}68 69	vector->container = kcalloc(count, struct_size, GFP_KERNEL);70 71	if (vector->container == NULL)72		return false;73 74	/* If caller didn't supply initial value then the default75	 * of all zeros is expected, which is exactly what dal_alloc()76	 * initialises the memory to. */77	if (NULL != initial_value) {78		for (i = 0; i < count; ++i)79			memmove(80				vector->container + i * struct_size,81				initial_value,82				struct_size);83	}84 85	vector->capacity = count;86	vector->struct_size = struct_size;87	vector->count = count;88	return true;89}90 91struct vector *dal_vector_presized_create(92	struct dc_context *ctx,93	uint32_t size,94	void *initial_value,95	uint32_t struct_size)96{97	struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL);98 99	if (vector == NULL)100		return NULL;101 102	if (dal_vector_presized_costruct(103		vector, ctx, size, initial_value, struct_size))104		return vector;105 106	BREAK_TO_DEBUGGER();107	kfree(vector);108	return NULL;109}110 111struct vector *dal_vector_create(112	struct dc_context *ctx,113	uint32_t capacity,114	uint32_t struct_size)115{116	struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL);117 118	if (vector == NULL)119		return NULL;120 121	if (dal_vector_construct(vector, ctx, capacity, struct_size))122		return vector;123 124	BREAK_TO_DEBUGGER();125	kfree(vector);126	return NULL;127}128 129void dal_vector_destruct(130	struct vector *vector)131{132	kfree(vector->container);133	vector->count = 0;134	vector->capacity = 0;135}136 137void dal_vector_destroy(138	struct vector **vector)139{140	if (vector == NULL || *vector == NULL)141		return;142	dal_vector_destruct(*vector);143	kfree(*vector);144	*vector = NULL;145}146 147uint32_t dal_vector_get_count(148	const struct vector *vector)149{150	return vector->count;151}152 153void *dal_vector_at_index(154	const struct vector *vector,155	uint32_t index)156{157	if (vector->container == NULL || index >= vector->count)158		return NULL;159	return vector->container + (index * vector->struct_size);160}161 162bool dal_vector_remove_at_index(163	struct vector *vector,164	uint32_t index)165{166	if (index >= vector->count)167		return false;168 169	if (index != vector->count - 1)170		memmove(171			vector->container + (index * vector->struct_size),172			vector->container + ((index + 1) * vector->struct_size),173			(vector->count - index - 1) * vector->struct_size);174	vector->count -= 1;175 176	return true;177}178 179void dal_vector_set_at_index(180	const struct vector *vector,181	const void *what,182	uint32_t index)183{184	void *where = dal_vector_at_index(vector, index);185 186	if (!where) {187		BREAK_TO_DEBUGGER();188		return;189	}190	memmove(191		where,192		what,193		vector->struct_size);194}195 196static inline uint32_t calc_increased_capacity(197	uint32_t old_capacity)198{199	return old_capacity * 2;200}201 202bool dal_vector_insert_at(203	struct vector *vector,204	const void *what,205	uint32_t position)206{207	uint8_t *insert_address;208 209	if (vector->count == vector->capacity) {210		if (!dal_vector_reserve(211			vector,212			calc_increased_capacity(vector->capacity)))213			return false;214	}215 216	insert_address = vector->container + (vector->struct_size * position);217 218	if (vector->count && position < vector->count)219		memmove(220			insert_address + vector->struct_size,221			insert_address,222			vector->struct_size * (vector->count - position));223 224	memmove(225		insert_address,226		what,227		vector->struct_size);228 229	vector->count++;230 231	return true;232}233 234bool dal_vector_append(235	struct vector *vector,236	const void *item)237{238	return dal_vector_insert_at(vector, item, vector->count);239}240 241struct vector *dal_vector_clone(242	const struct vector *vector)243{244	struct vector *vec_cloned;245	uint32_t count;246 247	/* create new vector */248	count = dal_vector_get_count(vector);249 250	if (count == 0)251		/* when count is 0 we still want to create clone of the vector252		 */253		vec_cloned = dal_vector_create(254			vector->ctx,255			vector->capacity,256			vector->struct_size);257	else258		/* Call "presized create" version, independently of how the259		 * original vector was created.260		 * The owner of original vector must know how to treat the new261		 * vector - as "presized" or as "regular".262		 * But from vector point of view it doesn't matter. */263		vec_cloned = dal_vector_presized_create(vector->ctx, count,264			NULL,/* no initial value */265			vector->struct_size);266 267	if (NULL == vec_cloned) {268		BREAK_TO_DEBUGGER();269		return NULL;270	}271 272	/* copy vector's data */273	memmove(vec_cloned->container, vector->container,274			vec_cloned->struct_size * vec_cloned->capacity);275 276	return vec_cloned;277}278 279uint32_t dal_vector_capacity(const struct vector *vector)280{281	return vector->capacity;282}283 284bool dal_vector_reserve(struct vector *vector, uint32_t capacity)285{286	void *new_container;287 288	if (capacity <= vector->capacity)289		return true;290 291	new_container = krealloc(vector->container,292				 capacity * vector->struct_size, GFP_KERNEL);293 294	if (new_container) {295		vector->container = new_container;296		vector->capacity = capacity;297		return true;298	}299 300	return false;301}302 303void dal_vector_clear(struct vector *vector)304{305	vector->count = 0;306}307