1 /* SPDX-License-Identifier: BSD-3-Clause */ 2 /* Copyright (c) 2023, 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 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 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 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 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 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 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