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