linux/drivers/infiniband/hw/ionic/ionic_res.h
Abhijit Gangurde f3bdbd4270 RDMA/ionic: Create device queues to support admin operations
Setup RDMA admin queues using device command exposed over
auxiliary device and manage these queues using ida.

Co-developed-by: Andrew Boyer <andrew.boyer@amd.com>
Signed-off-by: Andrew Boyer <andrew.boyer@amd.com>
Co-developed-by: Allen Hubbe <allen.hubbe@amd.com>
Signed-off-by: Allen Hubbe <allen.hubbe@amd.com>
Signed-off-by: Abhijit Gangurde <abhijit.gangurde@amd.com>
Link: https://patch.msgid.link/20250903061606.4139957-10-abhijit.gangurde@amd.com
Signed-off-by: Leon Romanovsky <leon@kernel.org>
2025-09-11 02:18:36 -04:00

154 lines
4.8 KiB
C

/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */
#ifndef _IONIC_RES_H_
#define _IONIC_RES_H_
#include <linux/kernel.h>
#include <linux/idr.h>
/**
* struct ionic_resid_bits - Number allocator based on IDA
*
* @inuse: IDA handle
* @inuse_size: Highest ID limit for IDA
*/
struct ionic_resid_bits {
struct ida inuse;
unsigned int inuse_size;
};
/**
* ionic_resid_init() - Initialize a resid allocator
* @resid: Uninitialized resid allocator
* @size: Capacity of the allocator
*
* Return: Zero on success, or negative error number
*/
static inline void ionic_resid_init(struct ionic_resid_bits *resid,
unsigned int size)
{
resid->inuse_size = size;
ida_init(&resid->inuse);
}
/**
* ionic_resid_destroy() - Destroy a resid allocator
* @resid: Resid allocator
*/
static inline void ionic_resid_destroy(struct ionic_resid_bits *resid)
{
ida_destroy(&resid->inuse);
}
/**
* ionic_resid_get_shared() - Allocate an available shared resource id
* @resid: Resid allocator
* @min: Smallest valid resource id
* @size: One after largest valid resource id
*
* Return: Resource id, or negative error number
*/
static inline int ionic_resid_get_shared(struct ionic_resid_bits *resid,
unsigned int min,
unsigned int size)
{
return ida_alloc_range(&resid->inuse, min, size - 1, GFP_KERNEL);
}
/**
* ionic_resid_get() - Allocate an available resource id
* @resid: Resid allocator
*
* Return: Resource id, or negative error number
*/
static inline int ionic_resid_get(struct ionic_resid_bits *resid)
{
return ionic_resid_get_shared(resid, 0, resid->inuse_size);
}
/**
* ionic_resid_put() - Free a resource id
* @resid: Resid allocator
* @id: Resource id
*/
static inline void ionic_resid_put(struct ionic_resid_bits *resid, int id)
{
ida_free(&resid->inuse, id);
}
/**
* ionic_bitid_to_qid() - Transform a resource bit index into a queue id
* @bitid: Bit index
* @qgrp_shift: Log2 number of queues per queue group
* @half_qid_shift: Log2 of half the total number of queues
*
* Return: Queue id
*
* Udma-constrained queues (QPs and CQs) are associated with their udma by
* queue group. Even queue groups are associated with udma0, and odd queue
* groups with udma1.
*
* For allocating queue ids, we want to arrange the bits into two halves,
* with the even queue groups of udma0 in the lower half of the bitset,
* and the odd queue groups of udma1 in the upper half of the bitset.
* Then, one or two calls of find_next_zero_bit can examine all the bits
* for queues of an entire udma.
*
* For example, assuming eight queue groups with qgrp qids per group:
*
* bitid 0*qgrp..1*qgrp-1 : qid 0*qgrp..1*qgrp-1
* bitid 1*qgrp..2*qgrp-1 : qid 2*qgrp..3*qgrp-1
* bitid 2*qgrp..3*qgrp-1 : qid 4*qgrp..5*qgrp-1
* bitid 3*qgrp..4*qgrp-1 : qid 6*qgrp..7*qgrp-1
* bitid 4*qgrp..5*qgrp-1 : qid 1*qgrp..2*qgrp-1
* bitid 5*qgrp..6*qgrp-1 : qid 3*qgrp..4*qgrp-1
* bitid 6*qgrp..7*qgrp-1 : qid 5*qgrp..6*qgrp-1
* bitid 7*qgrp..8*qgrp-1 : qid 7*qgrp..8*qgrp-1
*
* There are three important ranges of bits in the qid. There is the udma
* bit "U" at qgrp_shift, which is the least significant bit of the group
* index, and determines which udma a queue is associated with.
* The bits of lesser significance we can call the idx bits "I", which are
* the index of the queue within the group. The bits of greater significance
* we can call the grp bits "G", which are other bits of the group index that
* do not determine the udma. Those bits are just rearranged in the bit index
* in the bitset. A bitid has the udma bit in the most significant place,
* then the grp bits, then the idx bits.
*
* bitid: 00000000000000 U GGG IIIIII
* qid: 00000000000000 GGG U IIIIII
*
* Transforming from bit index to qid, or from qid to bit index, can be
* accomplished by rearranging the bits by masking and shifting.
*/
static inline u32 ionic_bitid_to_qid(u32 bitid, u8 qgrp_shift,
u8 half_qid_shift)
{
u32 udma_bit =
(bitid & BIT(half_qid_shift)) >> (half_qid_shift - qgrp_shift);
u32 grp_bits = (bitid & GENMASK(half_qid_shift - 1, qgrp_shift)) << 1;
u32 idx_bits = bitid & (BIT(qgrp_shift) - 1);
return grp_bits | udma_bit | idx_bits;
}
/**
* ionic_qid_to_bitid() - Transform a queue id into a resource bit index
* @qid: queue index
* @qgrp_shift: Log2 number of queues per queue group
* @half_qid_shift: Log2 of half the total number of queues
*
* Return: Resource bit index
*
* This is the inverse of ionic_bitid_to_qid().
*/
static inline u32 ionic_qid_to_bitid(u32 qid, u8 qgrp_shift, u8 half_qid_shift)
{
u32 udma_bit = (qid & BIT(qgrp_shift)) << (half_qid_shift - qgrp_shift);
u32 grp_bits = (qid & GENMASK(half_qid_shift, qgrp_shift + 1)) >> 1;
u32 idx_bits = qid & (BIT(qgrp_shift) - 1);
return udma_bit | grp_bits | idx_bits;
}
#endif /* _IONIC_RES_H_ */