^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) * SImple Tiler Allocator (SiTA): 2D and 1D allocation(reservation) algorithm
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) * Authors: Ravi Ramachandra <r.ramachandra@ti.com>,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) * Lajos Molnar <molnar@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) * Andy Gross <andy.gross@ti.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10) * This package is free software; you can redistribute it and/or modify
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) * it under the terms of the GNU General Public License version 2 as
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) * published by the Free Software Foundation.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17) *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) #include <linux/init.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) #include <linux/errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) #include <linux/sched.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23) #include <linux/wait.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) #include <linux/bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) #include <linux/slab.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) #include "tcm.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) static unsigned long mask[8];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) * pos position in bitmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) * w width in slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) * h height in slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33) * map ptr to bitmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) * stride slots in a row
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) static void free_slots(unsigned long pos, u16 w, u16 h,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37) unsigned long *map, u16 stride)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) for (i = 0; i < h; i++, pos += stride)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) bitmap_clear(map, pos, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46) * w width in slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) * pos ptr to position
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) * map ptr to bitmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) * num_bits number of bits in bitmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) static int r2l_b2t_1d(u16 w, unsigned long *pos, unsigned long *map,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) size_t num_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) unsigned long search_count = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) unsigned long bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56) bool area_found = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) *pos = num_bits - w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) while (search_count < num_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61) bit = find_next_bit(map, num_bits, *pos);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (bit - *pos >= w) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) /* found a long enough free area */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65) bitmap_set(map, *pos, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) area_found = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70) search_count = num_bits - bit + w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) *pos = bit - w;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) return (area_found) ? 0 : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78) * w = width in slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) * h = height in slots
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * a = align in slots (mask, 2^n-1, 0 is unaligned)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * offset = offset in bytes from 4KiB
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) * pos = position in bitmap for buffer
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) * map = bitmap ptr
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) * num_bits = size of bitmap
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85) * stride = bits in one row of container
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) static int l2r_t2b(u16 w, u16 h, u16 a, s16 offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) unsigned long *pos, unsigned long slot_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) unsigned long *map, size_t num_bits, size_t slot_stride)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) int i;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92) unsigned long index;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) bool area_free = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) unsigned long slots_per_band = PAGE_SIZE / slot_bytes;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) unsigned long bit_offset = (offset > 0) ? offset / slot_bytes : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96) unsigned long curr_bit = bit_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) /* reset alignment to 1 if we are matching a specific offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) /* adjust alignment - 1 to get to the format expected in bitmaps */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) a = (offset > 0) ? 0 : a - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) /* FIXME Return error if slots_per_band > stride */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) while (curr_bit < num_bits) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) *pos = bitmap_find_next_zero_area(map, num_bits, curr_bit, w,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) a);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) /* skip forward if we are not at right offset */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) if (bit_offset > 0 && (*pos % slots_per_band != bit_offset)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) curr_bit = ALIGN(*pos, slots_per_band) + bit_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) /* skip forward to next row if we overlap end of row */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) if ((*pos % slot_stride) + w > slot_stride) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) curr_bit = ALIGN(*pos, slot_stride) + bit_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) /* TODO: Handle overlapping 4K boundaries */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) /* break out of look if we will go past end of container */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) if ((*pos + slot_stride * h) > num_bits)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) /* generate mask that represents out matching pattern */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) bitmap_clear(mask, 0, slot_stride);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) bitmap_set(mask, (*pos % BITS_PER_LONG), w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) /* assume the area is free until we find an overlap */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) area_free = true;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) /* check subsequent rows to see if complete area is free */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) for (i = 1; i < h; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) index = *pos / BITS_PER_LONG + i * 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) if (bitmap_intersects(&map[index], mask,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) (*pos % BITS_PER_LONG) + w)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) area_free = false;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) if (area_free)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) /* go forward past this match */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) if (bit_offset > 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) curr_bit = ALIGN(*pos, slots_per_band) + bit_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) curr_bit = *pos + a + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) if (area_free) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) /* set area as in-use. iterate over rows */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) for (i = 0, index = *pos; i < h; i++, index += slot_stride)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) bitmap_set(map, index, w);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) return (area_free) ? 0 : -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) static s32 sita_reserve_1d(struct tcm *tcm, u32 num_slots,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) struct tcm_area *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) unsigned long pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) spin_lock(&(tcm->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) ret = r2l_b2t_1d(num_slots, &pos, tcm->bitmap, tcm->map_size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) area->p0.x = pos % tcm->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) area->p0.y = pos / tcm->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) area->p1.x = (pos + num_slots - 1) % tcm->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) area->p1.y = (pos + num_slots - 1) / tcm->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) spin_unlock(&(tcm->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) static s32 sita_reserve_2d(struct tcm *tcm, u16 h, u16 w, u16 align,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) s16 offset, u16 slot_bytes,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) struct tcm_area *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) unsigned long pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) int ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) spin_lock(&(tcm->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) ret = l2r_t2b(w, h, align, offset, &pos, slot_bytes, tcm->bitmap,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) tcm->map_size, tcm->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) if (!ret) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) area->p0.x = pos % tcm->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) area->p0.y = pos / tcm->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) area->p1.x = area->p0.x + w - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) area->p1.y = area->p0.y + h - 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) spin_unlock(&(tcm->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) return ret;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) static void sita_deinit(struct tcm *tcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) kfree(tcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) static s32 sita_free(struct tcm *tcm, struct tcm_area *area)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) unsigned long pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) u16 w, h;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) pos = area->p0.x + area->p0.y * tcm->width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) if (area->is2d) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) w = area->p1.x - area->p0.x + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) h = area->p1.y - area->p0.y + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) } else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) w = area->p1.x + area->p1.y * tcm->width - pos + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) h = 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) spin_lock(&(tcm->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) free_slots(pos, w, h, tcm->bitmap, tcm->width);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) spin_unlock(&(tcm->lock));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) struct tcm *sita_init(u16 width, u16 height)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) struct tcm *tcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) size_t map_size = BITS_TO_LONGS(width*height) * sizeof(unsigned long);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) if (width == 0 || height == 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) tcm = kzalloc(sizeof(*tcm) + map_size, GFP_KERNEL);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) if (!tcm)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) goto error;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) /* Updating the pointers to SiTA implementation APIs */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) tcm->height = height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) tcm->width = width;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) tcm->reserve_2d = sita_reserve_2d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) tcm->reserve_1d = sita_reserve_1d;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) tcm->free = sita_free;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) tcm->deinit = sita_deinit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) spin_lock_init(&tcm->lock);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) tcm->bitmap = (unsigned long *)(tcm + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) bitmap_clear(tcm->bitmap, 0, width*height);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) tcm->map_size = width*height;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) return tcm;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) error:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) kfree(tcm);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) return NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) }