1*f3bdbd42SAbhijit Gangurde /* SPDX-License-Identifier: GPL-2.0 */ 2*f3bdbd42SAbhijit Gangurde /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ 3*f3bdbd42SAbhijit Gangurde 4*f3bdbd42SAbhijit Gangurde #ifndef _IONIC_RES_H_ 5*f3bdbd42SAbhijit Gangurde #define _IONIC_RES_H_ 6*f3bdbd42SAbhijit Gangurde 7*f3bdbd42SAbhijit Gangurde #include <linux/kernel.h> 8*f3bdbd42SAbhijit Gangurde #include <linux/idr.h> 9*f3bdbd42SAbhijit Gangurde 10*f3bdbd42SAbhijit Gangurde /** 11*f3bdbd42SAbhijit Gangurde * struct ionic_resid_bits - Number allocator based on IDA 12*f3bdbd42SAbhijit Gangurde * 13*f3bdbd42SAbhijit Gangurde * @inuse: IDA handle 14*f3bdbd42SAbhijit Gangurde * @inuse_size: Highest ID limit for IDA 15*f3bdbd42SAbhijit Gangurde */ 16*f3bdbd42SAbhijit Gangurde struct ionic_resid_bits { 17*f3bdbd42SAbhijit Gangurde struct ida inuse; 18*f3bdbd42SAbhijit Gangurde unsigned int inuse_size; 19*f3bdbd42SAbhijit Gangurde }; 20*f3bdbd42SAbhijit Gangurde 21*f3bdbd42SAbhijit Gangurde /** 22*f3bdbd42SAbhijit Gangurde * ionic_resid_init() - Initialize a resid allocator 23*f3bdbd42SAbhijit Gangurde * @resid: Uninitialized resid allocator 24*f3bdbd42SAbhijit Gangurde * @size: Capacity of the allocator 25*f3bdbd42SAbhijit Gangurde * 26*f3bdbd42SAbhijit Gangurde * Return: Zero on success, or negative error number 27*f3bdbd42SAbhijit Gangurde */ 28*f3bdbd42SAbhijit Gangurde static inline void ionic_resid_init(struct ionic_resid_bits *resid, 29*f3bdbd42SAbhijit Gangurde unsigned int size) 30*f3bdbd42SAbhijit Gangurde { 31*f3bdbd42SAbhijit Gangurde resid->inuse_size = size; 32*f3bdbd42SAbhijit Gangurde ida_init(&resid->inuse); 33*f3bdbd42SAbhijit Gangurde } 34*f3bdbd42SAbhijit Gangurde 35*f3bdbd42SAbhijit Gangurde /** 36*f3bdbd42SAbhijit Gangurde * ionic_resid_destroy() - Destroy a resid allocator 37*f3bdbd42SAbhijit Gangurde * @resid: Resid allocator 38*f3bdbd42SAbhijit Gangurde */ 39*f3bdbd42SAbhijit Gangurde static inline void ionic_resid_destroy(struct ionic_resid_bits *resid) 40*f3bdbd42SAbhijit Gangurde { 41*f3bdbd42SAbhijit Gangurde ida_destroy(&resid->inuse); 42*f3bdbd42SAbhijit Gangurde } 43*f3bdbd42SAbhijit Gangurde 44*f3bdbd42SAbhijit Gangurde /** 45*f3bdbd42SAbhijit Gangurde * ionic_resid_get_shared() - Allocate an available shared resource id 46*f3bdbd42SAbhijit Gangurde * @resid: Resid allocator 47*f3bdbd42SAbhijit Gangurde * @min: Smallest valid resource id 48*f3bdbd42SAbhijit Gangurde * @size: One after largest valid resource id 49*f3bdbd42SAbhijit Gangurde * 50*f3bdbd42SAbhijit Gangurde * Return: Resource id, or negative error number 51*f3bdbd42SAbhijit Gangurde */ 52*f3bdbd42SAbhijit Gangurde static inline int ionic_resid_get_shared(struct ionic_resid_bits *resid, 53*f3bdbd42SAbhijit Gangurde unsigned int min, 54*f3bdbd42SAbhijit Gangurde unsigned int size) 55*f3bdbd42SAbhijit Gangurde { 56*f3bdbd42SAbhijit Gangurde return ida_alloc_range(&resid->inuse, min, size - 1, GFP_KERNEL); 57*f3bdbd42SAbhijit Gangurde } 58*f3bdbd42SAbhijit Gangurde 59*f3bdbd42SAbhijit Gangurde /** 60*f3bdbd42SAbhijit Gangurde * ionic_resid_get() - Allocate an available resource id 61*f3bdbd42SAbhijit Gangurde * @resid: Resid allocator 62*f3bdbd42SAbhijit Gangurde * 63*f3bdbd42SAbhijit Gangurde * Return: Resource id, or negative error number 64*f3bdbd42SAbhijit Gangurde */ 65*f3bdbd42SAbhijit Gangurde static inline int ionic_resid_get(struct ionic_resid_bits *resid) 66*f3bdbd42SAbhijit Gangurde { 67*f3bdbd42SAbhijit Gangurde return ionic_resid_get_shared(resid, 0, resid->inuse_size); 68*f3bdbd42SAbhijit Gangurde } 69*f3bdbd42SAbhijit Gangurde 70*f3bdbd42SAbhijit Gangurde /** 71*f3bdbd42SAbhijit Gangurde * ionic_resid_put() - Free a resource id 72*f3bdbd42SAbhijit Gangurde * @resid: Resid allocator 73*f3bdbd42SAbhijit Gangurde * @id: Resource id 74*f3bdbd42SAbhijit Gangurde */ 75*f3bdbd42SAbhijit Gangurde static inline void ionic_resid_put(struct ionic_resid_bits *resid, int id) 76*f3bdbd42SAbhijit Gangurde { 77*f3bdbd42SAbhijit Gangurde ida_free(&resid->inuse, id); 78*f3bdbd42SAbhijit Gangurde } 79*f3bdbd42SAbhijit Gangurde 80*f3bdbd42SAbhijit Gangurde /** 81*f3bdbd42SAbhijit Gangurde * ionic_bitid_to_qid() - Transform a resource bit index into a queue id 82*f3bdbd42SAbhijit Gangurde * @bitid: Bit index 83*f3bdbd42SAbhijit Gangurde * @qgrp_shift: Log2 number of queues per queue group 84*f3bdbd42SAbhijit Gangurde * @half_qid_shift: Log2 of half the total number of queues 85*f3bdbd42SAbhijit Gangurde * 86*f3bdbd42SAbhijit Gangurde * Return: Queue id 87*f3bdbd42SAbhijit Gangurde * 88*f3bdbd42SAbhijit Gangurde * Udma-constrained queues (QPs and CQs) are associated with their udma by 89*f3bdbd42SAbhijit Gangurde * queue group. Even queue groups are associated with udma0, and odd queue 90*f3bdbd42SAbhijit Gangurde * groups with udma1. 91*f3bdbd42SAbhijit Gangurde * 92*f3bdbd42SAbhijit Gangurde * For allocating queue ids, we want to arrange the bits into two halves, 93*f3bdbd42SAbhijit Gangurde * with the even queue groups of udma0 in the lower half of the bitset, 94*f3bdbd42SAbhijit Gangurde * and the odd queue groups of udma1 in the upper half of the bitset. 95*f3bdbd42SAbhijit Gangurde * Then, one or two calls of find_next_zero_bit can examine all the bits 96*f3bdbd42SAbhijit Gangurde * for queues of an entire udma. 97*f3bdbd42SAbhijit Gangurde * 98*f3bdbd42SAbhijit Gangurde * For example, assuming eight queue groups with qgrp qids per group: 99*f3bdbd42SAbhijit Gangurde * 100*f3bdbd42SAbhijit Gangurde * bitid 0*qgrp..1*qgrp-1 : qid 0*qgrp..1*qgrp-1 101*f3bdbd42SAbhijit Gangurde * bitid 1*qgrp..2*qgrp-1 : qid 2*qgrp..3*qgrp-1 102*f3bdbd42SAbhijit Gangurde * bitid 2*qgrp..3*qgrp-1 : qid 4*qgrp..5*qgrp-1 103*f3bdbd42SAbhijit Gangurde * bitid 3*qgrp..4*qgrp-1 : qid 6*qgrp..7*qgrp-1 104*f3bdbd42SAbhijit Gangurde * bitid 4*qgrp..5*qgrp-1 : qid 1*qgrp..2*qgrp-1 105*f3bdbd42SAbhijit Gangurde * bitid 5*qgrp..6*qgrp-1 : qid 3*qgrp..4*qgrp-1 106*f3bdbd42SAbhijit Gangurde * bitid 6*qgrp..7*qgrp-1 : qid 5*qgrp..6*qgrp-1 107*f3bdbd42SAbhijit Gangurde * bitid 7*qgrp..8*qgrp-1 : qid 7*qgrp..8*qgrp-1 108*f3bdbd42SAbhijit Gangurde * 109*f3bdbd42SAbhijit Gangurde * There are three important ranges of bits in the qid. There is the udma 110*f3bdbd42SAbhijit Gangurde * bit "U" at qgrp_shift, which is the least significant bit of the group 111*f3bdbd42SAbhijit Gangurde * index, and determines which udma a queue is associated with. 112*f3bdbd42SAbhijit Gangurde * The bits of lesser significance we can call the idx bits "I", which are 113*f3bdbd42SAbhijit Gangurde * the index of the queue within the group. The bits of greater significance 114*f3bdbd42SAbhijit Gangurde * we can call the grp bits "G", which are other bits of the group index that 115*f3bdbd42SAbhijit Gangurde * do not determine the udma. Those bits are just rearranged in the bit index 116*f3bdbd42SAbhijit Gangurde * in the bitset. A bitid has the udma bit in the most significant place, 117*f3bdbd42SAbhijit Gangurde * then the grp bits, then the idx bits. 118*f3bdbd42SAbhijit Gangurde * 119*f3bdbd42SAbhijit Gangurde * bitid: 00000000000000 U GGG IIIIII 120*f3bdbd42SAbhijit Gangurde * qid: 00000000000000 GGG U IIIIII 121*f3bdbd42SAbhijit Gangurde * 122*f3bdbd42SAbhijit Gangurde * Transforming from bit index to qid, or from qid to bit index, can be 123*f3bdbd42SAbhijit Gangurde * accomplished by rearranging the bits by masking and shifting. 124*f3bdbd42SAbhijit Gangurde */ 125*f3bdbd42SAbhijit Gangurde static inline u32 ionic_bitid_to_qid(u32 bitid, u8 qgrp_shift, 126*f3bdbd42SAbhijit Gangurde u8 half_qid_shift) 127*f3bdbd42SAbhijit Gangurde { 128*f3bdbd42SAbhijit Gangurde u32 udma_bit = 129*f3bdbd42SAbhijit Gangurde (bitid & BIT(half_qid_shift)) >> (half_qid_shift - qgrp_shift); 130*f3bdbd42SAbhijit Gangurde u32 grp_bits = (bitid & GENMASK(half_qid_shift - 1, qgrp_shift)) << 1; 131*f3bdbd42SAbhijit Gangurde u32 idx_bits = bitid & (BIT(qgrp_shift) - 1); 132*f3bdbd42SAbhijit Gangurde 133*f3bdbd42SAbhijit Gangurde return grp_bits | udma_bit | idx_bits; 134*f3bdbd42SAbhijit Gangurde } 135*f3bdbd42SAbhijit Gangurde 136*f3bdbd42SAbhijit Gangurde /** 137*f3bdbd42SAbhijit Gangurde * ionic_qid_to_bitid() - Transform a queue id into a resource bit index 138*f3bdbd42SAbhijit Gangurde * @qid: queue index 139*f3bdbd42SAbhijit Gangurde * @qgrp_shift: Log2 number of queues per queue group 140*f3bdbd42SAbhijit Gangurde * @half_qid_shift: Log2 of half the total number of queues 141*f3bdbd42SAbhijit Gangurde * 142*f3bdbd42SAbhijit Gangurde * Return: Resource bit index 143*f3bdbd42SAbhijit Gangurde * 144*f3bdbd42SAbhijit Gangurde * This is the inverse of ionic_bitid_to_qid(). 145*f3bdbd42SAbhijit Gangurde */ 146*f3bdbd42SAbhijit Gangurde static inline u32 ionic_qid_to_bitid(u32 qid, u8 qgrp_shift, u8 half_qid_shift) 147*f3bdbd42SAbhijit Gangurde { 148*f3bdbd42SAbhijit Gangurde u32 udma_bit = (qid & BIT(qgrp_shift)) << (half_qid_shift - qgrp_shift); 149*f3bdbd42SAbhijit Gangurde u32 grp_bits = (qid & GENMASK(half_qid_shift, qgrp_shift + 1)) >> 1; 150*f3bdbd42SAbhijit Gangurde u32 idx_bits = qid & (BIT(qgrp_shift) - 1); 151*f3bdbd42SAbhijit Gangurde 152*f3bdbd42SAbhijit Gangurde return udma_bit | grp_bits | idx_bits; 153*f3bdbd42SAbhijit Gangurde } 154*f3bdbd42SAbhijit Gangurde #endif /* _IONIC_RES_H_ */ 155