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