Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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 */
16struct 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 */
28static 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 */
39static 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 */
52static 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 */
65static 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 */
75static 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 */
125static 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 */
146static 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_ */