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