xref: /freebsd/sys/dev/ice/ice_resmgr.c (revision 015f8cc5b0c10336a048f37a7071ea03516de242)
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
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
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
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
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
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
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