171d10453SEric Joyner /* SPDX-License-Identifier: BSD-3-Clause */
2*015f8cc5SEric Joyner /* Copyright (c) 2024, Intel Corporation
371d10453SEric Joyner * All rights reserved.
471d10453SEric Joyner *
571d10453SEric Joyner * Redistribution and use in source and binary forms, with or without
671d10453SEric Joyner * modification, are permitted provided that the following conditions are met:
771d10453SEric Joyner *
871d10453SEric Joyner * 1. Redistributions of source code must retain the above copyright notice,
971d10453SEric Joyner * this list of conditions and the following disclaimer.
1071d10453SEric Joyner *
1171d10453SEric Joyner * 2. Redistributions in binary form must reproduce the above copyright
1271d10453SEric Joyner * notice, this list of conditions and the following disclaimer in the
1371d10453SEric Joyner * documentation and/or other materials provided with the distribution.
1471d10453SEric Joyner *
1571d10453SEric Joyner * 3. Neither the name of the Intel Corporation nor the names of its
1671d10453SEric Joyner * contributors may be used to endorse or promote products derived from
1771d10453SEric Joyner * this software without specific prior written permission.
1871d10453SEric Joyner *
1971d10453SEric Joyner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2071d10453SEric Joyner * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2171d10453SEric Joyner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2271d10453SEric Joyner * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2371d10453SEric Joyner * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2471d10453SEric Joyner * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2571d10453SEric Joyner * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2671d10453SEric Joyner * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2771d10453SEric Joyner * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2871d10453SEric Joyner * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
2971d10453SEric Joyner * POSSIBILITY OF SUCH DAMAGE.
3071d10453SEric Joyner */
3171d10453SEric Joyner
3271d10453SEric Joyner /**
3371d10453SEric Joyner * @file ice_resmgr.c
3471d10453SEric Joyner * @brief Resource allocation manager
3571d10453SEric Joyner *
3671d10453SEric Joyner * Manage device resource allocations for a PF, including assigning queues to
3771d10453SEric Joyner * VSIs, or managing interrupt allocations across the PF.
3871d10453SEric Joyner *
3971d10453SEric Joyner * It can handle contiguous and scattered resource allocations, and upon
4071d10453SEric Joyner * assigning them, will fill in the mapping array with a map of
4171d10453SEric Joyner * resource IDs to PF-space resource indices.
4271d10453SEric Joyner */
4371d10453SEric Joyner
4471d10453SEric Joyner #include "ice_resmgr.h"
4571d10453SEric Joyner
4671d10453SEric Joyner /**
4771d10453SEric Joyner * @var M_ICE_RESMGR
4871d10453SEric Joyner * @brief PF resource manager allocation type
4971d10453SEric Joyner *
5071d10453SEric Joyner * malloc(9) allocation type used by the resource manager code.
5171d10453SEric Joyner */
5271d10453SEric Joyner MALLOC_DEFINE(M_ICE_RESMGR, "ice-resmgr", "Intel(R) 100Gb Network Driver resmgr allocations");
5371d10453SEric Joyner
5471d10453SEric Joyner /*
5571d10453SEric Joyner * Public resource manager allocation functions
5671d10453SEric Joyner */
5771d10453SEric Joyner
5871d10453SEric Joyner /**
5971d10453SEric Joyner * ice_resmgr_init - Initialize a resource manager structure
6071d10453SEric Joyner * @resmgr: structure to track the resource manager state
6171d10453SEric Joyner * @num_res: the maximum number of resources it can assign
6271d10453SEric Joyner *
6371d10453SEric Joyner * Initialize the state of a resource manager structure, allocating space to
6471d10453SEric Joyner * assign up to the requested number of resources. Uses bit strings to track
6571d10453SEric Joyner * which resources have been assigned. This type of resmgr is intended to be
6671d10453SEric Joyner * used for tracking LAN queue assignments between VSIs.
6771d10453SEric Joyner */
6871d10453SEric Joyner int
ice_resmgr_init(struct ice_resmgr * resmgr,u16 num_res)6971d10453SEric Joyner ice_resmgr_init(struct ice_resmgr *resmgr, u16 num_res)
7071d10453SEric Joyner {
7171d10453SEric Joyner resmgr->resources = bit_alloc(num_res, M_ICE_RESMGR, M_NOWAIT);
7271d10453SEric Joyner if (resmgr->resources == NULL)
7371d10453SEric Joyner return (ENOMEM);
7471d10453SEric Joyner
7571d10453SEric Joyner resmgr->num_res = num_res;
7671d10453SEric Joyner resmgr->contig_only = false;
7771d10453SEric Joyner return (0);
7871d10453SEric Joyner }
7971d10453SEric Joyner
8071d10453SEric Joyner /**
8171d10453SEric Joyner * ice_resmgr_init_contig_only - Initialize a resource manager structure
8271d10453SEric Joyner * @resmgr: structure to track the resource manager state
8371d10453SEric Joyner * @num_res: the maximum number of resources it can assign
8471d10453SEric Joyner *
8571d10453SEric Joyner * Functions similarly to ice_resmgr_init(), but the resulting resmgr structure
8671d10453SEric Joyner * will only allow contiguous allocations. This type of resmgr is intended to
8771d10453SEric Joyner * be used with tracking device MSI-X interrupt allocations.
8871d10453SEric Joyner */
8971d10453SEric Joyner int
ice_resmgr_init_contig_only(struct ice_resmgr * resmgr,u16 num_res)9071d10453SEric Joyner ice_resmgr_init_contig_only(struct ice_resmgr *resmgr, u16 num_res)
9171d10453SEric Joyner {
9271d10453SEric Joyner int error;
9371d10453SEric Joyner
9471d10453SEric Joyner error = ice_resmgr_init(resmgr, num_res);
9571d10453SEric Joyner if (error)
9671d10453SEric Joyner return (error);
9771d10453SEric Joyner
9871d10453SEric Joyner resmgr->contig_only = true;
9971d10453SEric Joyner return (0);
10071d10453SEric Joyner }
10171d10453SEric Joyner
10271d10453SEric Joyner /**
10371d10453SEric Joyner * ice_resmgr_destroy - Deallocate memory associated with a resource manager
10471d10453SEric Joyner * @resmgr: resource manager structure
10571d10453SEric Joyner *
10671d10453SEric Joyner * De-allocates the bit string associated with this resource manager. It is
10771d10453SEric Joyner * expected that this function will not be called until all of the assigned
10871d10453SEric Joyner * resources have been released.
10971d10453SEric Joyner */
11071d10453SEric Joyner void
ice_resmgr_destroy(struct ice_resmgr * resmgr)11171d10453SEric Joyner ice_resmgr_destroy(struct ice_resmgr *resmgr)
11271d10453SEric Joyner {
11371d10453SEric Joyner if (resmgr->resources != NULL) {
11471d10453SEric Joyner #ifdef INVARIANTS
11571d10453SEric Joyner int set;
11671d10453SEric Joyner
11771d10453SEric Joyner bit_count(resmgr->resources, 0, resmgr->num_res, &set);
11871d10453SEric Joyner MPASS(set == 0);
11971d10453SEric Joyner #endif
12071d10453SEric Joyner
12171d10453SEric Joyner free(resmgr->resources, M_ICE_RESMGR);
12271d10453SEric Joyner resmgr->resources = NULL;
12371d10453SEric Joyner }
12471d10453SEric Joyner resmgr->num_res = 0;
12571d10453SEric Joyner }
12671d10453SEric Joyner
12771d10453SEric Joyner /*
12871d10453SEric Joyner * Resource allocation functions
12971d10453SEric Joyner */
13071d10453SEric Joyner
13171d10453SEric Joyner /**
13271d10453SEric Joyner * ice_resmgr_assign_contiguous - Assign contiguous mapping of resources
13371d10453SEric Joyner * @resmgr: resource manager structure
13471d10453SEric Joyner * @idx: memory to store mapping, at least num_res wide
13571d10453SEric Joyner * @num_res: the number of resources to assign
13671d10453SEric Joyner *
13771d10453SEric Joyner * Assign num_res number of contiguous resources into the idx mapping. On
13871d10453SEric Joyner * success, idx will be updated to map each index to a PF resource.
13971d10453SEric Joyner *
14071d10453SEric Joyner * This function guarantees that the resource mapping will be contiguous, and
14171d10453SEric Joyner * will fail if that is not possible.
14271d10453SEric Joyner */
14371d10453SEric Joyner int
ice_resmgr_assign_contiguous(struct ice_resmgr * resmgr,u16 * idx,u16 num_res)14471d10453SEric Joyner ice_resmgr_assign_contiguous(struct ice_resmgr *resmgr, u16 *idx, u16 num_res)
14571d10453SEric Joyner {
14671d10453SEric Joyner int start, i;
14771d10453SEric Joyner
14871d10453SEric Joyner bit_ffc_area(resmgr->resources, resmgr->num_res, num_res, &start);
14971d10453SEric Joyner if (start < 0)
15071d10453SEric Joyner return (ENOSPC);
15171d10453SEric Joyner
15271d10453SEric Joyner /* Set each bit and update the index array */
15371d10453SEric Joyner for (i = 0; i < num_res; i++) {
15471d10453SEric Joyner bit_set(resmgr->resources, start + i);
15571d10453SEric Joyner idx[i] = start + i;
15671d10453SEric Joyner }
15771d10453SEric Joyner
15871d10453SEric Joyner return (0);
15971d10453SEric Joyner }
16071d10453SEric Joyner
16171d10453SEric Joyner /**
16271d10453SEric Joyner * ice_resmgr_assign_scattered - Assign possibly scattered resources
16371d10453SEric Joyner * @resmgr: the resource manager structure
16471d10453SEric Joyner * @idx: memory to store associated resource mapping, at least num_res wide
16571d10453SEric Joyner * @num_res: the number of resources to assign
16671d10453SEric Joyner *
16771d10453SEric Joyner * Assign num_res number of resources into the idx_mapping. On success, idx
16871d10453SEric Joyner * will be updated to map each index to a PF-space resource.
16971d10453SEric Joyner *
17071d10453SEric Joyner * Queues may be allocated non-contiguously, and this function requires that
17171d10453SEric Joyner * num_res be less than the ICE_MAX_SCATTERED_QUEUES due to hardware
17271d10453SEric Joyner * limitations on scattered queue assignment.
17371d10453SEric Joyner */
17471d10453SEric Joyner int
ice_resmgr_assign_scattered(struct ice_resmgr * resmgr,u16 * idx,u16 num_res)17571d10453SEric Joyner ice_resmgr_assign_scattered(struct ice_resmgr *resmgr, u16 *idx, u16 num_res)
17671d10453SEric Joyner {
17771d10453SEric Joyner int index = 0, i;
17871d10453SEric Joyner
17971d10453SEric Joyner /* Scattered allocations won't work if they weren't allowed at resmgr
18071d10453SEric Joyner * creation time.
18171d10453SEric Joyner */
18271d10453SEric Joyner if (resmgr->contig_only)
18371d10453SEric Joyner return (EPERM);
18471d10453SEric Joyner
18571d10453SEric Joyner /* Hardware can only support a limited total of scattered queues for
18671d10453SEric Joyner * a single VSI
18771d10453SEric Joyner */
18871d10453SEric Joyner if (num_res > ICE_MAX_SCATTERED_QUEUES)
18971d10453SEric Joyner return (EOPNOTSUPP);
19071d10453SEric Joyner
19171d10453SEric Joyner for (i = 0; i < num_res; i++) {
19271d10453SEric Joyner bit_ffc_at(resmgr->resources, index, resmgr->num_res, &index);
19371d10453SEric Joyner if (index < 0)
19471d10453SEric Joyner goto err_no_space;
19571d10453SEric Joyner
19671d10453SEric Joyner bit_set(resmgr->resources, index);
19771d10453SEric Joyner idx[i] = index;
19871d10453SEric Joyner }
19971d10453SEric Joyner return (0);
20071d10453SEric Joyner
20171d10453SEric Joyner err_no_space:
20271d10453SEric Joyner /* Release any resources we did assign up to this point. */
20371d10453SEric Joyner ice_resmgr_release_map(resmgr, idx, i);
20471d10453SEric Joyner return (ENOSPC);
20571d10453SEric Joyner }
20671d10453SEric Joyner
20771d10453SEric Joyner /**
20871d10453SEric Joyner * ice_resmgr_release_map - Release previously assigned resource mapping
20971d10453SEric Joyner * @resmgr: the resource manager structure
21071d10453SEric Joyner * @idx: previously assigned resource mapping
21171d10453SEric Joyner * @num_res: number of resources in the mapping
21271d10453SEric Joyner *
21371d10453SEric Joyner * Clears the assignment of each resource in the provided resource index. Updates
21471d10453SEric Joyner * the idx to indicate that each of the virtual indexes have invalid resource
21571d10453SEric Joyner * mappings by assigning them to ICE_INVALID_RES_IDX.
21671d10453SEric Joyner */
21771d10453SEric Joyner void
ice_resmgr_release_map(struct ice_resmgr * resmgr,u16 * idx,u16 num_res)21871d10453SEric Joyner ice_resmgr_release_map(struct ice_resmgr *resmgr, u16 *idx, u16 num_res)
21971d10453SEric Joyner {
22071d10453SEric Joyner int i;
22171d10453SEric Joyner
22271d10453SEric Joyner for (i = 0; i < num_res; i++) {
22371d10453SEric Joyner if (idx[i] < resmgr->num_res)
22471d10453SEric Joyner bit_clear(resmgr->resources, idx[i]);
22571d10453SEric Joyner idx[i] = ICE_INVALID_RES_IDX;
22671d10453SEric Joyner }
22771d10453SEric Joyner }
228