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 "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
  53bool dal_vector_presized_costruct(
  54        struct vector *vector,
  55        struct dc_context *ctx,
  56        uint32_t count,
  57        void *initial_value,
  58        uint32_t struct_size)
  59{
  60        uint32_t i;
  61
  62        vector->container = NULL;
  63
  64        if (!struct_size || !count) {
  65                /* Container must be non-zero size*/
  66                BREAK_TO_DEBUGGER();
  67                return false;
  68        }
  69
  70        vector->container = kcalloc(count, struct_size, GFP_KERNEL);
  71
  72        if (vector->container == NULL)
  73                return false;
  74
  75        /* If caller didn't supply initial value then the default
  76         * of all zeros is expected, which is exactly what dal_alloc()
  77         * initialises the memory to. */
  78        if (NULL != initial_value) {
  79                for (i = 0; i < count; ++i)
  80                        memmove(
  81                                vector->container + i * struct_size,
  82                                initial_value,
  83                                struct_size);
  84        }
  85
  86        vector->capacity = count;
  87        vector->struct_size = struct_size;
  88        vector->count = count;
  89        return true;
  90}
  91
  92struct vector *dal_vector_presized_create(
  93        struct dc_context *ctx,
  94        uint32_t size,
  95        void *initial_value,
  96        uint32_t struct_size)
  97{
  98        struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL);
  99
 100        if (vector == NULL)
 101                return NULL;
 102
 103        if (dal_vector_presized_costruct(
 104                vector, ctx, size, initial_value, struct_size))
 105                return vector;
 106
 107        BREAK_TO_DEBUGGER();
 108        kfree(vector);
 109        return NULL;
 110}
 111
 112struct vector *dal_vector_create(
 113        struct dc_context *ctx,
 114        uint32_t capacity,
 115        uint32_t struct_size)
 116{
 117        struct vector *vector = kzalloc(sizeof(struct vector), GFP_KERNEL);
 118
 119        if (vector == NULL)
 120                return NULL;
 121
 122        if (dal_vector_construct(vector, ctx, capacity, struct_size))
 123                return vector;
 124
 125        BREAK_TO_DEBUGGER();
 126        kfree(vector);
 127        return NULL;
 128}
 129
 130void dal_vector_destruct(
 131        struct vector *vector)
 132{
 133        kfree(vector->container);
 134        vector->count = 0;
 135        vector->capacity = 0;
 136}
 137
 138void dal_vector_destroy(
 139        struct vector **vector)
 140{
 141        if (vector == NULL || *vector == NULL)
 142                return;
 143        dal_vector_destruct(*vector);
 144        kfree(*vector);
 145        *vector = NULL;
 146}
 147
 148uint32_t dal_vector_get_count(
 149        const struct vector *vector)
 150{
 151        return vector->count;
 152}
 153
 154void *dal_vector_at_index(
 155        const struct vector *vector,
 156        uint32_t index)
 157{
 158        if (vector->container == NULL || index >= vector->count)
 159                return NULL;
 160        return vector->container + (index * vector->struct_size);
 161}
 162
 163bool dal_vector_remove_at_index(
 164        struct vector *vector,
 165        uint32_t index)
 166{
 167        if (index >= vector->count)
 168                return false;
 169
 170        if (index != vector->count - 1)
 171                memmove(
 172                        vector->container + (index * vector->struct_size),
 173                        vector->container + ((index + 1) * vector->struct_size),
 174                        (vector->count - index - 1) * vector->struct_size);
 175        vector->count -= 1;
 176
 177        return true;
 178}
 179
 180void dal_vector_set_at_index(
 181        const struct vector *vector,
 182        const void *what,
 183        uint32_t index)
 184{
 185        void *where = dal_vector_at_index(vector, index);
 186
 187        if (!where) {
 188                BREAK_TO_DEBUGGER();
 189                return;
 190        }
 191        memmove(
 192                where,
 193                what,
 194                vector->struct_size);
 195}
 196
 197static inline uint32_t calc_increased_capacity(
 198        uint32_t old_capacity)
 199{
 200        return old_capacity * 2;
 201}
 202
 203bool dal_vector_insert_at(
 204        struct vector *vector,
 205        const void *what,
 206        uint32_t position)
 207{
 208        uint8_t *insert_address;
 209
 210        if (vector->count == vector->capacity) {
 211                if (!dal_vector_reserve(
 212                        vector,
 213                        calc_increased_capacity(vector->capacity)))
 214                        return false;
 215        }
 216
 217        insert_address = vector->container + (vector->struct_size * position);
 218
 219        if (vector->count && position < vector->count)
 220                memmove(
 221                        insert_address + vector->struct_size,
 222                        insert_address,
 223                        vector->struct_size * (vector->count - position));
 224
 225        memmove(
 226                insert_address,
 227                what,
 228                vector->struct_size);
 229
 230        vector->count++;
 231
 232        return true;
 233}
 234
 235bool dal_vector_append(
 236        struct vector *vector,
 237        const void *item)
 238{
 239        return dal_vector_insert_at(vector, item, vector->count);
 240}
 241
 242struct vector *dal_vector_clone(
 243        const struct vector *vector)
 244{
 245        struct vector *vec_cloned;
 246        uint32_t count;
 247
 248        /* create new vector */
 249        count = dal_vector_get_count(vector);
 250
 251        if (count == 0)
 252                /* when count is 0 we still want to create clone of the vector
 253                 */
 254                vec_cloned = dal_vector_create(
 255                        vector->ctx,
 256                        vector->capacity,
 257                        vector->struct_size);
 258        else
 259                /* Call "presized create" version, independently of how the
 260                 * original vector was created.
 261                 * The owner of original vector must know how to treat the new
 262                 * vector - as "presized" or as "regular".
 263                 * But from vector point of view it doesn't matter. */
 264                vec_cloned = dal_vector_presized_create(vector->ctx, count,
 265                        NULL,/* no initial value */
 266                        vector->struct_size);
 267
 268        if (NULL == vec_cloned) {
 269                BREAK_TO_DEBUGGER();
 270                return NULL;
 271        }
 272
 273        /* copy vector's data */
 274        memmove(vec_cloned->container, vector->container,
 275                        vec_cloned->struct_size * vec_cloned->capacity);
 276
 277        return vec_cloned;
 278}
 279
 280uint32_t dal_vector_capacity(const struct vector *vector)
 281{
 282        return vector->capacity;
 283}
 284
 285bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
 286{
 287        void *new_container;
 288
 289        if (capacity <= vector->capacity)
 290                return true;
 291
 292        new_container = krealloc(vector->container,
 293                                 capacity * vector->struct_size, GFP_KERNEL);
 294
 295        if (new_container) {
 296                vector->container = new_container;
 297                vector->capacity = capacity;
 298                return true;
 299        }
 300
 301        return false;
 302}
 303
 304void dal_vector_clear(struct vector *vector)
 305{
 306        vector->count = 0;
 307}
 308