/* SPDX-License-Identifier: GPL-2.0 *//* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */#ifndef _IONIC_QUEUE_H_#define _IONIC_QUEUE_H_#include <linux/io.h>#include <ionic_regs.h>#define IONIC_MAX_DEPTH 0xffff#define IONIC_MAX_CQ_DEPTH 0xffff#define IONIC_CQ_RING_ARM IONIC_DBELL_RING_1#define IONIC_CQ_RING_SOL IONIC_DBELL_RING_2/** * struct ionic_queue - Ring buffer used between device and driver * @size: Size of the buffer, in bytes * @dma: Dma address of the buffer * @ptr: Buffer virtual address * @prod: Driver position in the queue * @cons: Device position in the queue * @mask: Capacity of the queue, subtracting the hole * This value is equal to ((1 << depth_log2) - 1) * @depth_log2: Log base two size depth of the queue * @stride_log2: Log base two size of an element in the queue * @dbell: Doorbell identifying bits */struct ionic_queue { size_t size; dma_addr_t dma; void *ptr; u16 prod; u16 cons; u16 mask; u8 depth_log2; u8 stride_log2; u64 dbell;};/** * ionic_queue_init() - Initialize user space queue * @q: Uninitialized queue structure * @dma_dev: DMA device for mapping * @depth: Depth of the queue * @stride: Size of each element of the queue * * Return: status code */int ionic_queue_init(struct ionic_queue *q, struct device *dma_dev, int depth, size_t stride);/** * ionic_queue_destroy() - Destroy user space queue * @q: Queue structure * @dma_dev: DMA device for mapping * * Return: status code */void ionic_queue_destroy(struct ionic_queue *q, struct device *dma_dev);/** * ionic_queue_empty() - Test if queue is empty * @q: Queue structure * * This is only valid for to-device queues. * * Return: is empty */static inline bool ionic_queue_empty(struct ionic_queue *q){ return q->prod == q->cons;}/** * ionic_queue_length() - Get the current length of the queue * @q: Queue structure * * This is only valid for to-device queues. * * Return: length */static inline u16 ionic_queue_length(struct ionic_queue *q){ return (q->prod - q->cons) & q->mask;}/** * ionic_queue_length_remaining() - Get the remaining length of the queue * @q: Queue structure * * This is only valid for to-device queues. * * Return: length remaining */static inline u16 ionic_queue_length_remaining(struct ionic_queue *q){ return q->mask - ionic_queue_length(q);}/** * ionic_queue_full() - Test if queue is full * @q: Queue structure * * This is only valid for to-device queues. * * Return: is full */static inline bool ionic_queue_full(struct ionic_queue *q){ return q->mask == ionic_queue_length(q);}/** * ionic_color_wrap() - Flip the color if prod is wrapped * @prod: Queue index just after advancing * @color: Queue color just prior to advancing the index * * Return: color after advancing the index */static inline bool ionic_color_wrap(u16 prod, bool color){ /* logical xor color with (prod == 0) */ return color != (prod == 0);}/** * ionic_queue_at() - Get the element at the given index * @q: Queue structure * @idx: Index in the queue * * The index must be within the bounds of the queue. It is not checked here. * * Return: pointer to element at index */static inline void *ionic_queue_at(struct ionic_queue *q, u16 idx){ return q->ptr + ((unsigned long)idx << q->stride_log2);}/** * ionic_queue_at_prod() - Get the element at the producer index * @q: Queue structure * * Return: pointer to element at producer index */static inline void *ionic_queue_at_prod(struct ionic_queue *q){ return ionic_queue_at(q, q->prod);}/** * ionic_queue_at_cons() - Get the element at the consumer index * @q: Queue structure * * Return: pointer to element at consumer index */static inline void *ionic_queue_at_cons(struct ionic_queue *q){ return ionic_queue_at(q, q->cons);}/** * ionic_queue_next() - Compute the next index * @q: Queue structure * @idx: Index * * Return: next index after idx */static inline u16 ionic_queue_next(struct ionic_queue *q, u16 idx){ return (idx + 1) & q->mask;}/** * ionic_queue_produce() - Increase the producer index * @q: Queue structure * * Caller must ensure that the queue is not full. It is not checked here. */static inline void ionic_queue_produce(struct ionic_queue *q){ q->prod = ionic_queue_next(q, q->prod);}/** * ionic_queue_consume() - Increase the consumer index * @q: Queue structure * * Caller must ensure that the queue is not empty. It is not checked here. * * This is only valid for to-device queues. */static inline void ionic_queue_consume(struct ionic_queue *q){ q->cons = ionic_queue_next(q, q->cons);}/** * ionic_queue_consume_entries() - Increase the consumer index by entries * @q: Queue structure * @entries: Number of entries to increment * * Caller must ensure that the queue is not empty. It is not checked here. * * This is only valid for to-device queues. */static inline void ionic_queue_consume_entries(struct ionic_queue *q, u16 entries){ q->cons = (q->cons + entries) & q->mask;}/** * ionic_queue_dbell_init() - Initialize doorbell bits for queue id * @q: Queue structure * @qid: Queue identifying number */static inline void ionic_queue_dbell_init(struct ionic_queue *q, u32 qid){ q->dbell = IONIC_DBELL_QID(qid);}/** * ionic_queue_dbell_val() - Get current doorbell update value * @q: Queue structure * * Return: current doorbell update value */static inline u64 ionic_queue_dbell_val(struct ionic_queue *q){ return q->dbell | q->prod;}#endif /* _IONIC_QUEUE_H_ */
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */
#ifndef _IONIC_QUEUE_H_
#define _IONIC_QUEUE_H_
#include <linux/io.h>
#include <ionic_regs.h>
#define IONIC_MAX_DEPTH 0xffff
#define IONIC_MAX_CQ_DEPTH 0xffff
#define IONIC_CQ_RING_ARM IONIC_DBELL_RING_1
#define IONIC_CQ_RING_SOL IONIC_DBELL_RING_2
/**
* struct ionic_queue - Ring buffer used between device and driver
* @size: Size of the buffer, in bytes
* @dma: Dma address of the buffer
* @ptr: Buffer virtual address
* @prod: Driver position in the queue
* @cons: Device position in the queue
* @mask: Capacity of the queue, subtracting the hole
* This value is equal to ((1 << depth_log2) - 1)
* @depth_log2: Log base two size depth of the queue
* @stride_log2: Log base two size of an element in the queue
* @dbell: Doorbell identifying bits
*/
struct ionic_queue {
size_t size;
dma_addr_t dma;
void *ptr;
u16 prod;
u16 cons;
u16 mask;
u8 depth_log2;
u8 stride_log2;
u64 dbell;
};
/**
* ionic_queue_init() - Initialize user space queue
* @q: Uninitialized queue structure
* @dma_dev: DMA device for mapping
* @depth: Depth of the queue
* @stride: Size of each element of the queue
*
* Return: status code
*/
int ionic_queue_init(struct ionic_queue *q, struct device *dma_dev,
int depth, size_t stride);
/**
* ionic_queue_destroy() - Destroy user space queue
* @q: Queue structure
* @dma_dev: DMA device for mapping
*
* Return: status code
*/
void ionic_queue_destroy(struct ionic_queue *q, struct device *dma_dev);
/**
* ionic_queue_empty() - Test if queue is empty
* @q: Queue structure
*
* This is only valid for to-device queues.
*
* Return: is empty
*/
static inline bool ionic_queue_empty(struct ionic_queue *q)
{
return q->prod == q->cons;
}
/**
* ionic_queue_length() - Get the current length of the queue
* @q: Queue structure
*
* This is only valid for to-device queues.
*
* Return: length
*/
static inline u16 ionic_queue_length(struct ionic_queue *q)
{
return (q->prod - q->cons) & q->mask;
}
/**
* ionic_queue_length_remaining() - Get the remaining length of the queue
* @q: Queue structure
*
* This is only valid for to-device queues.
*
* Return: length remaining
*/
static inline u16 ionic_queue_length_remaining(struct ionic_queue *q)
{
return q->mask - ionic_queue_length(q);
}
/**
* ionic_queue_full() - Test if queue is full
* @q: Queue structure
*
* This is only valid for to-device queues.
*
* Return: is full
*/
static inline bool ionic_queue_full(struct ionic_queue *q)
{
return q->mask == ionic_queue_length(q);
}
/**
* ionic_color_wrap() - Flip the color if prod is wrapped
* @prod: Queue index just after advancing
* @color: Queue color just prior to advancing the index
*
* Return: color after advancing the index
*/
static inline bool ionic_color_wrap(u16 prod, bool color)
{
/* logical xor color with (prod == 0) */
return color != (prod == 0);
}
/**
* ionic_queue_at() - Get the element at the given index
* @q: Queue structure
* @idx: Index in the queue
*
* The index must be within the bounds of the queue. It is not checked here.
*
* Return: pointer to element at index
*/
static inline void *ionic_queue_at(struct ionic_queue *q, u16 idx)
{
return q->ptr + ((unsigned long)idx << q->stride_log2);
}
/**
* ionic_queue_at_prod() - Get the element at the producer index
* @q: Queue structure
*
* Return: pointer to element at producer index
*/
static inline void *ionic_queue_at_prod(struct ionic_queue *q)
{
return ionic_queue_at(q, q->prod);
}
/**
* ionic_queue_at_cons() - Get the element at the consumer index
* @q: Queue structure
*
* Return: pointer to element at consumer index
*/
static inline void *ionic_queue_at_cons(struct ionic_queue *q)
{
return ionic_queue_at(q, q->cons);
}
/**
* ionic_queue_next() - Compute the next index
* @q: Queue structure
* @idx: Index
*
* Return: next index after idx
*/
static inline u16 ionic_queue_next(struct ionic_queue *q, u16 idx)
{
return (idx + 1) & q->mask;
}
/**
* ionic_queue_produce() - Increase the producer index
* @q: Queue structure
*
* Caller must ensure that the queue is not full. It is not checked here.
*/
static inline void ionic_queue_produce(struct ionic_queue *q)
{
q->prod = ionic_queue_next(q, q->prod);
}
/**
* ionic_queue_consume() - Increase the consumer index
* @q: Queue structure
*
* Caller must ensure that the queue is not empty. It is not checked here.
*
* This is only valid for to-device queues.
*/
static inline void ionic_queue_consume(struct ionic_queue *q)
{
q->cons = ionic_queue_next(q, q->cons);
}
/**
* ionic_queue_consume_entries() - Increase the consumer index by entries
* @q: Queue structure
* @entries: Number of entries to increment
*
* Caller must ensure that the queue is not empty. It is not checked here.
*
* This is only valid for to-device queues.
*/
static inline void ionic_queue_consume_entries(struct ionic_queue *q,
u16 entries)
{
q->cons = (q->cons + entries) & q->mask;
}
/**
* ionic_queue_dbell_init() - Initialize doorbell bits for queue id
* @q: Queue structure
* @qid: Queue identifying number
*/
static inline void ionic_queue_dbell_init(struct ionic_queue *q, u32 qid)
{
q->dbell = IONIC_DBELL_QID(qid);
}
/**
* ionic_queue_dbell_val() - Get current doorbell update value
* @q: Queue structure
*
* Return: current doorbell update value
*/
static inline u64 ionic_queue_dbell_val(struct ionic_queue *q)
{
return q->dbell | q->prod;
}
#endif /* _IONIC_QUEUE_H_ */