xref: /freebsd/sys/dev/ice/ice_resmgr.c (revision 015f8cc5)
1 /* SPDX-License-Identifier: BSD-3-Clause */
2 /*  Copyright (c) 2024, 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 
32 /**
33  * @file ice_resmgr.c
34  * @brief Resource allocation manager
35  *
36  * Manage device resource allocations for a PF, including assigning queues to
37  * VSIs, or managing interrupt allocations across the PF.
38  *
39  * It can handle contiguous and scattered resource allocations, and upon
40  * assigning them, will fill in the mapping array with a map of
41  * resource IDs to PF-space resource indices.
42  */
43 
44 #include "ice_resmgr.h"
45 
46 /**
47  * @var M_ICE_RESMGR
48  * @brief PF resource manager allocation type
49  *
50  * malloc(9) allocation type used by the resource manager code.
51  */
52 MALLOC_DEFINE(M_ICE_RESMGR, "ice-resmgr", "Intel(R) 100Gb Network Driver resmgr allocations");
53 
54 /*
55  * Public resource manager allocation functions
56  */
57 
58 /**
59  * ice_resmgr_init - Initialize a resource manager structure
60  * @resmgr: structure to track the resource manager state
61  * @num_res: the maximum number of resources it can assign
62  *
63  * Initialize the state of a resource manager structure, allocating space to
64  * assign up to the requested number of resources. Uses bit strings to track
65  * which resources have been assigned. This type of resmgr is intended to be
66  * used for tracking LAN queue assignments between VSIs.
67  */
68 int
ice_resmgr_init(struct ice_resmgr * resmgr,u16 num_res)69 ice_resmgr_init(struct ice_resmgr *resmgr, u16 num_res)
70 {
71 	resmgr->resources = bit_alloc(num_res, M_ICE_RESMGR, M_NOWAIT);
72 	if (resmgr->resources == NULL)
73 		return (ENOMEM);
74 
75 	resmgr->num_res = num_res;
76 	resmgr->contig_only = false;
77 	return (0);
78 }
79 
80 /**
81  * ice_resmgr_init_contig_only - Initialize a resource manager structure
82  * @resmgr: structure to track the resource manager state
83  * @num_res: the maximum number of resources it can assign
84  *
85  * Functions similarly to ice_resmgr_init(), but the resulting resmgr structure
86  * will only allow contiguous allocations. This type of resmgr is intended to
87  * be used with tracking device MSI-X interrupt allocations.
88  */
89 int
ice_resmgr_init_contig_only(struct ice_resmgr * resmgr,u16 num_res)90 ice_resmgr_init_contig_only(struct ice_resmgr *resmgr, u16 num_res)
91 {
92 	int error;
93 
94 	error = ice_resmgr_init(resmgr, num_res);
95 	if (error)
96 		return (error);
97 
98 	resmgr->contig_only = true;
99 	return (0);
100 }
101 
102 /**
103  * ice_resmgr_destroy - Deallocate memory associated with a resource manager
104  * @resmgr: resource manager structure
105  *
106  * De-allocates the bit string associated with this resource manager. It is
107  * expected that this function will not be called until all of the assigned
108  * resources have been released.
109  */
110 void
ice_resmgr_destroy(struct ice_resmgr * resmgr)111 ice_resmgr_destroy(struct ice_resmgr *resmgr)
112 {
113 	if (resmgr->resources != NULL) {
114 #ifdef INVARIANTS
115 		int set;
116 
117 		bit_count(resmgr->resources, 0, resmgr->num_res, &set);
118 		MPASS(set == 0);
119 #endif
120 
121 		free(resmgr->resources, M_ICE_RESMGR);
122 		resmgr->resources = NULL;
123 	}
124 	resmgr->num_res = 0;
125 }
126 
127 /*
128  * Resource allocation functions
129  */
130 
131 /**
132  * ice_resmgr_assign_contiguous - Assign contiguous mapping of resources
133  * @resmgr: resource manager structure
134  * @idx: memory to store mapping, at least num_res wide
135  * @num_res: the number of resources to assign
136  *
137  * Assign num_res number of contiguous resources into the idx mapping. On
138  * success, idx will be updated to map each index to a PF resource.
139  *
140  * This function guarantees that the resource mapping will be contiguous, and
141  * will fail if that is not possible.
142  */
143 int
ice_resmgr_assign_contiguous(struct ice_resmgr * resmgr,u16 * idx,u16 num_res)144 ice_resmgr_assign_contiguous(struct ice_resmgr *resmgr, u16 *idx, u16 num_res)
145 {
146 	int start, i;
147 
148 	bit_ffc_area(resmgr->resources, resmgr->num_res, num_res, &start);
149 	if (start < 0)
150 		return (ENOSPC);
151 
152 	/* Set each bit and update the index array */
153 	for (i = 0; i < num_res; i++) {
154 		bit_set(resmgr->resources, start + i);
155 		idx[i] = start + i;
156 	}
157 
158 	return (0);
159 }
160 
161 /**
162  * ice_resmgr_assign_scattered - Assign possibly scattered resources
163  * @resmgr: the resource manager structure
164  * @idx: memory to store associated resource mapping, at least num_res wide
165  * @num_res: the number of resources to assign
166  *
167  * Assign num_res number of resources into the idx_mapping. On success, idx
168  * will be updated to map each index to a PF-space resource.
169  *
170  * Queues may be allocated non-contiguously, and this function requires that
171  * num_res be less than the ICE_MAX_SCATTERED_QUEUES due to hardware
172  * limitations on scattered queue assignment.
173  */
174 int
ice_resmgr_assign_scattered(struct ice_resmgr * resmgr,u16 * idx,u16 num_res)175 ice_resmgr_assign_scattered(struct ice_resmgr *resmgr, u16 *idx, u16 num_res)
176 {
177 	int index = 0, i;
178 
179 	/* Scattered allocations won't work if they weren't allowed at resmgr
180 	 * creation time.
181 	 */
182 	if (resmgr->contig_only)
183 		return (EPERM);
184 
185 	/* Hardware can only support a limited total of scattered queues for
186 	 * a single VSI
187 	 */
188 	if (num_res > ICE_MAX_SCATTERED_QUEUES)
189 		return (EOPNOTSUPP);
190 
191 	for (i = 0; i < num_res; i++) {
192 		bit_ffc_at(resmgr->resources, index, resmgr->num_res, &index);
193 		if (index < 0)
194 			goto err_no_space;
195 
196 		bit_set(resmgr->resources, index);
197 		idx[i] = index;
198 	}
199 	return (0);
200 
201 err_no_space:
202 	/* Release any resources we did assign up to this point. */
203 	ice_resmgr_release_map(resmgr, idx, i);
204 	return (ENOSPC);
205 }
206 
207 /**
208  * ice_resmgr_release_map - Release previously assigned resource mapping
209  * @resmgr: the resource manager structure
210  * @idx: previously assigned resource mapping
211  * @num_res: number of resources in the mapping
212  *
213  * Clears the assignment of each resource in the provided resource index. Updates
214  * the idx to indicate that each of the virtual indexes have invalid resource
215  * mappings by assigning them to ICE_INVALID_RES_IDX.
216  */
217 void
ice_resmgr_release_map(struct ice_resmgr * resmgr,u16 * idx,u16 num_res)218 ice_resmgr_release_map(struct ice_resmgr *resmgr, u16 *idx, u16 num_res)
219 {
220 	int i;
221 
222 	for (i = 0; i < num_res; i++) {
223 		if (idx[i] < resmgr->num_res)
224 			bit_clear(resmgr->resources, idx[i]);
225 		idx[i] = ICE_INVALID_RES_IDX;
226 	}
227 }
228