1 /******************************************************************************
2
3 Copyright (c) 2013-2018, Intel Corporation
4 All rights reserved.
5
6 Redistribution and use in source and binary forms, with or without
7 modification, are permitted provided that the following conditions are met:
8
9 1. Redistributions of source code must retain the above copyright notice,
10 this list of conditions and the following disclaimer.
11
12 2. Redistributions in binary form must reproduce the above copyright
13 notice, this list of conditions and the following disclaimer in the
14 documentation and/or other materials provided with the distribution.
15
16 3. Neither the name of the Intel Corporation nor the names of its
17 contributors may be used to endorse or promote products derived from
18 this software without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
24 LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27 INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 POSSIBILITY OF SUCH DAMAGE.
31
32 ******************************************************************************/
33 /*$FreeBSD$*/
34
35
36 #include "ixl_pf_qmgr.h"
37
38 static int ixl_pf_qmgr_find_free_contiguous_block(struct ixl_pf_qmgr *qmgr, int num);
39
40 int
41 ixl_pf_qmgr_init(struct ixl_pf_qmgr *qmgr, u16 num_queues)
42 {
43 if (num_queues < 1)
44 return (EINVAL);
45
46 qmgr->num_queues = num_queues;
47 qmgr->qinfo = malloc(num_queues * sizeof(struct ixl_pf_qmgr_qinfo),
48 M_IXL, M_ZERO | M_NOWAIT);
49 if (qmgr->qinfo == NULL)
50 return ENOMEM;
51
52 return (0);
53 }
54
55 int
56 ixl_pf_qmgr_alloc_contiguous(struct ixl_pf_qmgr *qmgr, u16 num, struct ixl_pf_qtag *qtag)
57 {
58 int i;
59 int avail;
60 int block_start;
61 u16 alloc_size;
62
63 if (qtag == NULL || num < 1)
64 return (EINVAL);
65
66 /* We have to allocate in power-of-two chunks, so get next power of two */
67 alloc_size = (u16)next_power_of_two(num);
68
69 /* Don't try if there aren't enough queues */
70 avail = ixl_pf_qmgr_get_num_free(qmgr);
71 if (avail < alloc_size)
72 return (ENOSPC);
73
74 block_start = ixl_pf_qmgr_find_free_contiguous_block(qmgr, alloc_size);
75 if (block_start < 0)
76 return (ENOSPC);
77
78 /* Mark queues as allocated */
79 for (i = block_start; i < block_start + alloc_size; i++)
80 qmgr->qinfo[i].allocated = true;
81
82 bzero(qtag, sizeof(*qtag));
83 qtag->qmgr = qmgr;
84 qtag->type = IXL_PF_QALLOC_CONTIGUOUS;
85 qtag->qidx[0] = block_start;
86 qtag->num_allocated = alloc_size;
87 qtag->num_active = num;
88
89 return (0);
90 }
91
92 /*
93 * NB: indices is u16 because this is the queue index width used in the Add VSI AQ command
94 */
95 int
96 ixl_pf_qmgr_alloc_scattered(struct ixl_pf_qmgr *qmgr, u16 num, struct ixl_pf_qtag *qtag)
97 {
98 int i;
99 int avail, count = 0;
100 u16 alloc_size;
101
102 if (qtag == NULL || num < 1 || num > 16)
103 return (EINVAL);
104
105 /* We have to allocate in power-of-two chunks, so get next power of two */
106 alloc_size = (u16)next_power_of_two(num);
107
108 avail = ixl_pf_qmgr_get_num_free(qmgr);
109 if (avail < alloc_size)
110 return (ENOSPC);
111
112 bzero(qtag, sizeof(*qtag));
113 qtag->qmgr = qmgr;
114 qtag->type = IXL_PF_QALLOC_SCATTERED;
115 qtag->num_active = num;
116 qtag->num_allocated = alloc_size;
117
118 for (i = 0; i < qmgr->num_queues; i++) {
119 if (!qmgr->qinfo[i].allocated) {
120 qtag->qidx[count] = i;
121 count++;
122 qmgr->qinfo[i].allocated = true;
123 if (count == alloc_size)
124 return (0);
125 }
126 }
127
128 // Shouldn't get here
129 return (EDOOFUS);
130 }
131
132 int
133 ixl_pf_qmgr_release(struct ixl_pf_qmgr *qmgr, struct ixl_pf_qtag *qtag)
134 {
135 u16 i, qidx;
136
137 if (qtag == NULL)
138 return (EINVAL);
139
140 if (qtag->type == IXL_PF_QALLOC_SCATTERED) {
141 for (i = 0; i < qtag->num_allocated; i++) {
142 qidx = qtag->qidx[i];
143 bzero(&qmgr->qinfo[qidx], sizeof(qmgr->qinfo[qidx]));
144 }
145 } else {
146 u16 first_index = qtag->qidx[0];
147 for (i = first_index; i < first_index + qtag->num_allocated; i++)
148 bzero(&qmgr->qinfo[i], sizeof(qmgr->qinfo[qidx]));
149 }
150
151 qtag->qmgr = NULL;
152 return (0);
153 }
154
155 int
156 ixl_pf_qmgr_get_num_queues(struct ixl_pf_qmgr *qmgr)
157 {
158 return (qmgr->num_queues);
159 }
160
161 /*
162 * ERJ: This assumes the info array isn't longer than INT_MAX.
163 * This assumption might cause a y3k bug or something, I'm sure.
164 */
165 int
166 ixl_pf_qmgr_get_num_free(struct ixl_pf_qmgr *qmgr)
167 {
168 int count = 0;
169
170 for (int i = 0; i < qmgr->num_queues; i++) {
171 if (!qmgr->qinfo[i].allocated)
172 count++;
173 }
174
175 return (count);
176 }
177
178 int
179 ixl_pf_qmgr_get_first_free(struct ixl_pf_qmgr *qmgr, u16 start)
180 {
181 int i;
182
183 if (start > qmgr->num_queues - 1)
184 return (-EINVAL);
185
186 for (i = start; i < qmgr->num_queues; i++) {
187 if (qmgr->qinfo[i].allocated)
188 continue;
189 else
190 return (i);
191 }
192
193 // No free queues
194 return (-ENOSPC);
195 }
196
197 void
198 ixl_pf_qmgr_destroy(struct ixl_pf_qmgr *qmgr)
199 {
200 free(qmgr->qinfo, M_IXL);
201 qmgr->qinfo = NULL;
202 }
203
204 void
205 ixl_pf_qmgr_mark_queue_enabled(struct ixl_pf_qtag *qtag, u16 vsi_qidx, bool tx)
206 {
207 MPASS(qtag != NULL);
208
209 struct ixl_pf_qmgr *qmgr = qtag->qmgr;
210 u16 pf_qidx = ixl_pf_qidx_from_vsi_qidx(qtag, vsi_qidx);
211 if (tx)
212 qmgr->qinfo[pf_qidx].tx_enabled = true;
213 else
214 qmgr->qinfo[pf_qidx].rx_enabled = true;
215 }
216
217 void
218 ixl_pf_qmgr_mark_queue_disabled(struct ixl_pf_qtag *qtag, u16 vsi_qidx, bool tx)
219 {
220 MPASS(qtag != NULL);
221
222 struct ixl_pf_qmgr *qmgr = qtag->qmgr;
223 u16 pf_qidx = ixl_pf_qidx_from_vsi_qidx(qtag, vsi_qidx);
224 if (tx)
225 qmgr->qinfo[pf_qidx].tx_enabled = false;
226 else
227 qmgr->qinfo[pf_qidx].rx_enabled = false;
228 }
229
230 void
231 ixl_pf_qmgr_mark_queue_configured(struct ixl_pf_qtag *qtag, u16 vsi_qidx, bool tx)
232 {
233 MPASS(qtag != NULL);
234
235 struct ixl_pf_qmgr *qmgr = qtag->qmgr;
236 u16 pf_qidx = ixl_pf_qidx_from_vsi_qidx(qtag, vsi_qidx);
237 if (tx)
238 qmgr->qinfo[pf_qidx].tx_configured = true;
239 else
240 qmgr->qinfo[pf_qidx].rx_configured = true;
241 }
242
243 bool
244 ixl_pf_qmgr_is_queue_enabled(struct ixl_pf_qtag *qtag, u16 vsi_qidx, bool tx)
245 {
246 MPASS(qtag != NULL);
247
248 struct ixl_pf_qmgr *qmgr = qtag->qmgr;
249 u16 pf_qidx = ixl_pf_qidx_from_vsi_qidx(qtag, vsi_qidx);
250 if (tx)
251 return (qmgr->qinfo[pf_qidx].tx_enabled);
252 else
253 return (qmgr->qinfo[pf_qidx].rx_enabled);
254 }
255
256 bool
257 ixl_pf_qmgr_is_queue_configured(struct ixl_pf_qtag *qtag, u16 vsi_qidx, bool tx)
258 {
259 MPASS(qtag != NULL);
260
261 struct ixl_pf_qmgr *qmgr = qtag->qmgr;
262 u16 pf_qidx = ixl_pf_qidx_from_vsi_qidx(qtag, vsi_qidx);
263 if (tx)
264 return (qmgr->qinfo[pf_qidx].tx_configured);
265 else
266 return (qmgr->qinfo[pf_qidx].rx_configured);
267 }
268
269 void
270 ixl_pf_qmgr_clear_queue_flags(struct ixl_pf_qtag *qtag)
271 {
272 MPASS(qtag != NULL);
273
274 struct ixl_pf_qmgr *qmgr = qtag->qmgr;
275 for (u16 i = 0; i < qtag->num_allocated; i++) {
276 u16 pf_qidx = ixl_pf_qidx_from_vsi_qidx(qtag, i);
277
278 qmgr->qinfo[pf_qidx].tx_configured = 0;
279 qmgr->qinfo[pf_qidx].rx_configured = 0;
280 qmgr->qinfo[pf_qidx].rx_enabled = 0;
281 qmgr->qinfo[pf_qidx].tx_enabled = 0;
282 }
283 }
284
285 u16
286 ixl_pf_qidx_from_vsi_qidx(struct ixl_pf_qtag *qtag, u16 index)
287 {
288 MPASS(index < qtag->num_allocated);
289
290 if (qtag->type == IXL_PF_QALLOC_CONTIGUOUS)
291 return qtag->first_qidx + index;
292 else
293 return qtag->qidx[index];
294 }
295
296 /* Static Functions */
297
298 static int
299 ixl_pf_qmgr_find_free_contiguous_block(struct ixl_pf_qmgr *qmgr, int num)
300 {
301 int i;
302 int count = 0;
303 bool block_started = false;
304 int possible_start;
305
306 for (i = 0; i < qmgr->num_queues; i++) {
307 if (!qmgr->qinfo[i].allocated) {
308 if (!block_started) {
309 block_started = true;
310 possible_start = i;
311 }
312 count++;
313 if (count == num)
314 return (possible_start);
315 } else { /* this queue is already allocated */
316 block_started = false;
317 count = 0;
318 }
319 }
320
321 /* Can't find a contiguous block of the requested size */
322 return (-1);
323 }
324
Cache object: 9d755497862c5a71d5d95cf8fe32382c
|