| 1 |
|
| 2 |
|
| 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
|