]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ixl/ixl_pf_qmgr.c
bhnd(9): Fix a few mandoc related issues
[FreeBSD/FreeBSD.git] / sys / dev / ixl / ixl_pf_qmgr.c
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