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 } 229