]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/ice/ice_resmgr.c
dma: import snapshot 2021-07-10
[FreeBSD/FreeBSD.git] / sys / dev / ice / ice_resmgr.c
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*  Copyright (c) 2021, Intel Corporation
3  *  All rights reserved.
4  *
5  *  Redistribution and use in source and binary forms, with or without
6  *  modification, are permitted provided that the following conditions are met:
7  *
8  *   1. Redistributions of source code must retain the above copyright notice,
9  *      this list of conditions and the following disclaimer.
10  *
11  *   2. Redistributions in binary form must reproduce the above copyright
12  *      notice, this list of conditions and the following disclaimer in the
13  *      documentation and/or other materials provided with the distribution.
14  *
15  *   3. Neither the name of the Intel Corporation nor the names of its
16  *      contributors may be used to endorse or promote products derived from
17  *      this software without specific prior written permission.
18  *
19  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23  *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24  *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25  *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27  *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28  *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29  *  POSSIBILITY OF SUCH DAMAGE.
30  */
31 /*$FreeBSD$*/
32
33 /**
34  * @file ice_resmgr.c
35  * @brief Resource allocation manager
36  *
37  * Manage device resource allocations for a PF, including assigning queues to
38  * VSIs, or managing interrupt allocations across the PF.
39  *
40  * It can handle contiguous and scattered resource allocations, and upon
41  * assigning them, will fill in the mapping array with a map of
42  * resource IDs to PF-space resource indices.
43  */
44
45 #include "ice_resmgr.h"
46
47 /**
48  * @var M_ICE_RESMGR
49  * @brief PF resource manager allocation type
50  *
51  * malloc(9) allocation type used by the resource manager code.
52  */
53 MALLOC_DEFINE(M_ICE_RESMGR, "ice-resmgr", "Intel(R) 100Gb Network Driver resmgr allocations");
54
55 /*
56  * Public resource manager allocation functions
57  */
58
59 /**
60  * ice_resmgr_init - Initialize a resource manager structure
61  * @resmgr: structure to track the resource manager state
62  * @num_res: the maximum number of resources it can assign
63  *
64  * Initialize the state of a resource manager structure, allocating space to
65  * assign up to the requested number of resources. Uses bit strings to track
66  * which resources have been assigned. This type of resmgr is intended to be
67  * used for tracking LAN queue assignments between VSIs.
68  */
69 int
70 ice_resmgr_init(struct ice_resmgr *resmgr, u16 num_res)
71 {
72         resmgr->resources = bit_alloc(num_res, M_ICE_RESMGR, M_NOWAIT);
73         if (resmgr->resources == NULL)
74                 return (ENOMEM);
75
76         resmgr->num_res = num_res;
77         resmgr->contig_only = false;
78         return (0);
79 }
80
81 /**
82  * ice_resmgr_init_contig_only - Initialize a resource manager structure
83  * @resmgr: structure to track the resource manager state
84  * @num_res: the maximum number of resources it can assign
85  *
86  * Functions similarly to ice_resmgr_init(), but the resulting resmgr structure
87  * will only allow contiguous allocations. This type of resmgr is intended to
88  * be used with tracking device MSI-X interrupt allocations.
89  */
90 int
91 ice_resmgr_init_contig_only(struct ice_resmgr *resmgr, u16 num_res)
92 {
93         int error;
94
95         error = ice_resmgr_init(resmgr, num_res);
96         if (error)
97                 return (error);
98
99         resmgr->contig_only = true;
100         return (0);
101 }
102
103 /**
104  * ice_resmgr_destroy - Deallocate memory associated with a resource manager
105  * @resmgr: resource manager structure
106  *
107  * De-allocates the bit string associated with this resource manager. It is
108  * expected that this function will not be called until all of the assigned
109  * resources have been released.
110  */
111 void
112 ice_resmgr_destroy(struct ice_resmgr *resmgr)
113 {
114         if (resmgr->resources != NULL) {
115 #ifdef INVARIANTS
116                 int set;
117
118                 bit_count(resmgr->resources, 0, resmgr->num_res, &set);
119                 MPASS(set == 0);
120 #endif
121
122                 free(resmgr->resources, M_ICE_RESMGR);
123                 resmgr->resources = NULL;
124         }
125         resmgr->num_res = 0;
126 }
127
128 /*
129  * Resource allocation functions
130  */
131
132 /**
133  * ice_resmgr_assign_contiguous - Assign contiguous mapping of resources
134  * @resmgr: resource manager structure
135  * @idx: memory to store mapping, at least num_res wide
136  * @num_res: the number of resources to assign
137  *
138  * Assign num_res number of contiguous resources into the idx mapping. On
139  * success, idx will be updated to map each index to a PF resource.
140  *
141  * This function guarantees that the resource mapping will be contiguous, and
142  * will fail if that is not possible.
143  */
144 int
145 ice_resmgr_assign_contiguous(struct ice_resmgr *resmgr, u16 *idx, u16 num_res)
146 {
147         int start, i;
148
149         bit_ffc_area(resmgr->resources, resmgr->num_res, num_res, &start);
150         if (start < 0)
151                 return (ENOSPC);
152
153         /* Set each bit and update the index array */
154         for (i = 0; i < num_res; i++) {
155                 bit_set(resmgr->resources, start + i);
156                 idx[i] = start + i;
157         }
158
159         return (0);
160 }
161
162 /**
163  * ice_resmgr_assign_scattered - Assign possibly scattered resources
164  * @resmgr: the resource manager structure
165  * @idx: memory to store associated resource mapping, at least num_res wide
166  * @num_res: the number of resources to assign
167  *
168  * Assign num_res number of resources into the idx_mapping. On success, idx
169  * will be updated to map each index to a PF-space resource.
170  *
171  * Queues may be allocated non-contiguously, and this function requires that
172  * num_res be less than the ICE_MAX_SCATTERED_QUEUES due to hardware
173  * limitations on scattered queue assignment.
174  */
175 int
176 ice_resmgr_assign_scattered(struct ice_resmgr *resmgr, u16 *idx, u16 num_res)
177 {
178         int index = 0, i;
179
180         /* Scattered allocations won't work if they weren't allowed at resmgr
181          * creation time.
182          */
183         if (resmgr->contig_only)
184                 return (EPERM);
185
186         /* Hardware can only support a limited total of scattered queues for
187          * a single VSI
188          */
189         if (num_res > ICE_MAX_SCATTERED_QUEUES)
190                 return (EOPNOTSUPP);
191
192         for (i = 0; i < num_res; i++) {
193                 bit_ffc_at(resmgr->resources, index, resmgr->num_res, &index);
194                 if (index < 0)
195                         goto err_no_space;
196
197                 bit_set(resmgr->resources, index);
198                 idx[i] = index;
199         }
200         return (0);
201
202 err_no_space:
203         /* Release any resources we did assign up to this point. */
204         ice_resmgr_release_map(resmgr, idx, i);
205         return (ENOSPC);
206 }
207
208 /**
209  * ice_resmgr_release_map - Release previously assigned resource mapping
210  * @resmgr: the resource manager structure
211  * @idx: previously assigned resource mapping
212  * @num_res: number of resources in the mapping
213  *
214  * Clears the assignment of each resource in the provided resource index. Updates
215  * the idx to indicate that each of the virtual indexes have invalid resource
216  * mappings by assigning them to ICE_INVALID_RES_IDX.
217  */
218 void
219 ice_resmgr_release_map(struct ice_resmgr *resmgr, u16 *idx, u16 num_res)
220 {
221         int i;
222
223         for (i = 0; i < num_res; i++) {
224                 if (idx[i] < resmgr->num_res)
225                         bit_clear(resmgr->resources, idx[i]);
226                 idx[i] = ICE_INVALID_RES_IDX;
227         }
228 }