Commit | Line | Data |
---|---|---|
800f879a AT |
1 | /* |
2 | * Copyright 2010-2017 Intel Corporation. | |
3 | * | |
4 | * This program is free software; you can redistribute it and/or modify | |
5 | * it under the terms of the GNU General Public License, version 2, | |
6 | * as published by the Free Software Foundation. | |
7 | * | |
8 | * This program is distributed in the hope that it will be useful, | |
9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
11 | * General Public License for more details. | |
12 | * | |
13 | * Disclaimer: The codes contained in these modules may be specific to | |
14 | * the Intel Software Development Platform codenamed Knights Ferry, | |
15 | * and the Intel product codenamed Knights Corner, and are not backward | |
16 | * compatible with other Intel products. Additionally, Intel will NOT | |
17 | * support the codes or instruction set in future products. | |
18 | * | |
19 | * Intel offers no warranty of any kind regarding the code. This code is | |
20 | * licensed on an "AS IS" basis and Intel is not obligated to provide | |
21 | * any support, assistance, installation, training, or other services | |
22 | * of any kind. Intel is also not obligated to provide any updates, | |
23 | * enhancements or extensions. Intel specifically disclaims any warranty | |
24 | * of merchantability, non-infringement, fitness for any particular | |
25 | * purpose, and any other warranty. | |
26 | * | |
27 | * Further, Intel disclaims all liability of any kind, including but | |
28 | * not limited to liability for infringement of any proprietary rights, | |
29 | * relating to the use of the code, even if Intel is notified of the | |
30 | * possibility of such liability. Except as expressly stated in an Intel | |
31 | * license agreement provided with this code and agreed upon with Intel, | |
32 | * no license, express or implied, by estoppel or otherwise, to any | |
33 | * intellectual property rights is granted herein. | |
34 | */ | |
35 | ||
36 | /***************************************************************************\ | |
37 | manage available nodes for VaGenAddress | |
38 | \***************************************************************************/ | |
39 | #include "mic/micscif.h" | |
40 | ||
41 | /***************************************************************************\ | |
42 | FUNCTION: va_node_init | |
43 | ||
44 | DESCRIPTION: constructor for allocator for GfxGenAddress | |
45 | \***************************************************************************/ | |
46 | void va_node_init(struct va_node_allocator *node) | |
47 | { | |
48 | node->pp_slab_directory = 0; | |
49 | node->slab_shift = 7; /* 2^7 -> 128 nodes in the slab */ | |
50 | node->nodes_in_slab = 1<<node->slab_shift; | |
51 | node->slab_mask = (node->nodes_in_slab-1); | |
52 | node->num_slabs = 0; | |
53 | node->num_free_slabs = 0; | |
54 | node->free_list = invalid_va_node_index; | |
55 | } | |
56 | ||
57 | int va_node_is_valid(uint32_t index) | |
58 | { | |
59 | return invalid_va_node_index != index; | |
60 | } | |
61 | ||
62 | /************************************************************************** *\ | |
63 | FUNCTION: va_node_destroy | |
64 | ||
65 | DESCRIPTION: destructor for allocator for GfxGenAddress | |
66 | \************************************************************************** */ | |
67 | void va_node_destroy(struct va_node_allocator *node) | |
68 | { | |
69 | uint32_t i; | |
70 | if (node->pp_slab_directory) { | |
71 | for (i = 0; i < node->num_slabs; i++) { | |
72 | kfree(node->pp_slab_directory[i]); | |
73 | node->pp_slab_directory[i] = NULL; | |
74 | } | |
75 | kfree(node->pp_slab_directory); | |
76 | node->pp_slab_directory = NULL; | |
77 | } | |
78 | } | |
79 | ||
80 | /* ************************************************************************* *\ | |
81 | FUNCTION: va_node_realloc | |
82 | ||
83 | DESCRIPTION: va_node_realloc to add more node arrays | |
84 | \* ************************************************************************* */ | |
85 | static int va_node_realloc(struct va_node_allocator *node) | |
86 | { | |
87 | uint32_t growSlabs = 2 * (node->num_slabs) + 1; | |
88 | struct va_node **ppGrowDirectory = | |
89 | kzalloc(sizeof(struct va_node *) * growSlabs, GFP_KERNEL); | |
90 | uint32_t i; | |
91 | ||
92 | if (!ppGrowDirectory) | |
93 | return -ENOMEM; | |
94 | ||
95 | if (node->num_slabs) { | |
96 | for (i = 0; i < node->num_slabs; i++) | |
97 | ppGrowDirectory[i] = node->pp_slab_directory[i]; | |
98 | kfree(node->pp_slab_directory); | |
99 | node->pp_slab_directory = NULL; | |
100 | } | |
101 | node->pp_slab_directory = ppGrowDirectory; | |
102 | node->num_free_slabs = growSlabs - node->num_slabs; | |
103 | return 0; | |
104 | } | |
105 | ||
106 | /* ************************************************************************* *\ | |
107 | FUNCTION: va_node_grow | |
108 | ||
109 | DESCRIPTION: add a node array | |
110 | \* ************************************************************************* */ | |
111 | static int va_node_grow(struct va_node_allocator *node) | |
112 | { | |
113 | struct va_node *pNewSlab; | |
114 | uint32_t i, start; | |
115 | int ret; | |
116 | ||
117 | if (!node->num_free_slabs) | |
118 | if ((ret = va_node_realloc(node)) < 0) | |
119 | return ret; | |
120 | ||
121 | pNewSlab = kzalloc(sizeof(struct va_node) * | |
122 | node->nodes_in_slab, GFP_KERNEL); | |
123 | if (pNewSlab) | |
124 | node->pp_slab_directory[node->num_slabs] = pNewSlab; | |
125 | else | |
126 | return -ENOMEM; | |
127 | ||
128 | /*-------------------------------------------------------- | |
129 | * add new nodes to free list | |
130 | * slightly better than just calling free() for each index | |
131 | */ | |
132 | start = node->num_slabs * node->nodes_in_slab; | |
133 | for (i = 0; i < (node->nodes_in_slab-1); i++) | |
134 | /* we could optimize this, but why bother? */ | |
135 | pNewSlab[i].next = start + i + 1; | |
136 | /* add new allocations to start of list */ | |
137 | pNewSlab[node->nodes_in_slab-1].next = node->free_list; | |
138 | node->free_list = start; | |
139 | /*-------------------------------------------------------*/ | |
140 | ||
141 | /* update bookkeeping for array of arrays */ | |
142 | node->num_slabs++; | |
143 | node->num_free_slabs--; | |
144 | return 0; | |
145 | } | |
146 | ||
147 | /* ************************************************************************* *\ | |
148 | FUNCTION: va_node_get | |
149 | ||
150 | DESCRIPTION: return a node reference from index | |
151 | \* ************************************************************************* */ | |
152 | struct va_node *va_node_get(struct va_node_allocator *node, uint32_t index) | |
153 | { | |
154 | uint32_t slabIndex = index >> node->slab_shift; | |
155 | uint32_t nodeIndex = index & node->slab_mask; | |
156 | ||
157 | return &node->pp_slab_directory[slabIndex][nodeIndex]; | |
158 | } | |
159 | ||
160 | /* ************************************************************************* *\ | |
161 | FUNCTION: va_node_alloc | |
162 | ||
163 | DESCRIPTION: return 0 on success with valid index in out_alloc or errno on failure. | |
164 | \* ************************************************************************* */ | |
165 | int va_node_alloc(struct va_node_allocator *node, uint32_t *out_alloc) | |
166 | { | |
167 | int ret; | |
168 | ||
169 | if (!va_node_is_valid(node->free_list)) | |
170 | if ((ret = va_node_grow(node)) < 0) | |
171 | return ret; | |
172 | *out_alloc = node->free_list; | |
173 | node->free_list = (va_node_get(node, *out_alloc))->next; | |
174 | return 0; | |
175 | } | |
176 | ||
177 | /* ************************************************************************* *\ | |
178 | FUNCTION: va_node_free | |
179 | ||
180 | DESCRIPTION: make a node available | |
181 | \* ************************************************************************* */ | |
182 | void va_node_free(struct va_node_allocator *node, uint32_t index) | |
183 | { | |
184 | struct va_node *tmp = va_node_get(node, index); | |
185 | tmp->next = node->free_list; | |
186 | node->free_list = index; | |
187 | } |