234 lines · 5.5 KB · C
RawDownload
/* 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_ */