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