1*f3bdbd42SAbhijit Gangurde /* SPDX-License-Identifier: GPL-2.0 */ 2*f3bdbd42SAbhijit Gangurde /* Copyright (C) 2018-2025, Advanced Micro Devices, Inc. */ 3*f3bdbd42SAbhijit Gangurde 4*f3bdbd42SAbhijit Gangurde #ifndef _IONIC_QUEUE_H_ 5*f3bdbd42SAbhijit Gangurde #define _IONIC_QUEUE_H_ 6*f3bdbd42SAbhijit Gangurde 7*f3bdbd42SAbhijit Gangurde #include <linux/io.h> 8*f3bdbd42SAbhijit Gangurde #include <ionic_regs.h> 9*f3bdbd42SAbhijit Gangurde 10*f3bdbd42SAbhijit Gangurde #define IONIC_MAX_DEPTH 0xffff 11*f3bdbd42SAbhijit Gangurde #define IONIC_MAX_CQ_DEPTH 0xffff 12*f3bdbd42SAbhijit Gangurde #define IONIC_CQ_RING_ARM IONIC_DBELL_RING_1 13*f3bdbd42SAbhijit Gangurde #define IONIC_CQ_RING_SOL IONIC_DBELL_RING_2 14*f3bdbd42SAbhijit Gangurde 15*f3bdbd42SAbhijit Gangurde /** 16*f3bdbd42SAbhijit Gangurde * struct ionic_queue - Ring buffer used between device and driver 17*f3bdbd42SAbhijit Gangurde * @size: Size of the buffer, in bytes 18*f3bdbd42SAbhijit Gangurde * @dma: Dma address of the buffer 19*f3bdbd42SAbhijit Gangurde * @ptr: Buffer virtual address 20*f3bdbd42SAbhijit Gangurde * @prod: Driver position in the queue 21*f3bdbd42SAbhijit Gangurde * @cons: Device position in the queue 22*f3bdbd42SAbhijit Gangurde * @mask: Capacity of the queue, subtracting the hole 23*f3bdbd42SAbhijit Gangurde * This value is equal to ((1 << depth_log2) - 1) 24*f3bdbd42SAbhijit Gangurde * @depth_log2: Log base two size depth of the queue 25*f3bdbd42SAbhijit Gangurde * @stride_log2: Log base two size of an element in the queue 26*f3bdbd42SAbhijit Gangurde * @dbell: Doorbell identifying bits 27*f3bdbd42SAbhijit Gangurde */ 28*f3bdbd42SAbhijit Gangurde struct ionic_queue { 29*f3bdbd42SAbhijit Gangurde size_t size; 30*f3bdbd42SAbhijit Gangurde dma_addr_t dma; 31*f3bdbd42SAbhijit Gangurde void *ptr; 32*f3bdbd42SAbhijit Gangurde u16 prod; 33*f3bdbd42SAbhijit Gangurde u16 cons; 34*f3bdbd42SAbhijit Gangurde u16 mask; 35*f3bdbd42SAbhijit Gangurde u8 depth_log2; 36*f3bdbd42SAbhijit Gangurde u8 stride_log2; 37*f3bdbd42SAbhijit Gangurde u64 dbell; 38*f3bdbd42SAbhijit Gangurde }; 39*f3bdbd42SAbhijit Gangurde 40*f3bdbd42SAbhijit Gangurde /** 41*f3bdbd42SAbhijit Gangurde * ionic_queue_init() - Initialize user space queue 42*f3bdbd42SAbhijit Gangurde * @q: Uninitialized queue structure 43*f3bdbd42SAbhijit Gangurde * @dma_dev: DMA device for mapping 44*f3bdbd42SAbhijit Gangurde * @depth: Depth of the queue 45*f3bdbd42SAbhijit Gangurde * @stride: Size of each element of the queue 46*f3bdbd42SAbhijit Gangurde * 47*f3bdbd42SAbhijit Gangurde * Return: status code 48*f3bdbd42SAbhijit Gangurde */ 49*f3bdbd42SAbhijit Gangurde int ionic_queue_init(struct ionic_queue *q, struct device *dma_dev, 50*f3bdbd42SAbhijit Gangurde int depth, size_t stride); 51*f3bdbd42SAbhijit Gangurde 52*f3bdbd42SAbhijit Gangurde /** 53*f3bdbd42SAbhijit Gangurde * ionic_queue_destroy() - Destroy user space queue 54*f3bdbd42SAbhijit Gangurde * @q: Queue structure 55*f3bdbd42SAbhijit Gangurde * @dma_dev: DMA device for mapping 56*f3bdbd42SAbhijit Gangurde * 57*f3bdbd42SAbhijit Gangurde * Return: status code 58*f3bdbd42SAbhijit Gangurde */ 59*f3bdbd42SAbhijit Gangurde void ionic_queue_destroy(struct ionic_queue *q, struct device *dma_dev); 60*f3bdbd42SAbhijit Gangurde 61*f3bdbd42SAbhijit Gangurde /** 62*f3bdbd42SAbhijit Gangurde * ionic_queue_empty() - Test if queue is empty 63*f3bdbd42SAbhijit Gangurde * @q: Queue structure 64*f3bdbd42SAbhijit Gangurde * 65*f3bdbd42SAbhijit Gangurde * This is only valid for to-device queues. 66*f3bdbd42SAbhijit Gangurde * 67*f3bdbd42SAbhijit Gangurde * Return: is empty 68*f3bdbd42SAbhijit Gangurde */ 69*f3bdbd42SAbhijit Gangurde static inline bool ionic_queue_empty(struct ionic_queue *q) 70*f3bdbd42SAbhijit Gangurde { 71*f3bdbd42SAbhijit Gangurde return q->prod == q->cons; 72*f3bdbd42SAbhijit Gangurde } 73*f3bdbd42SAbhijit Gangurde 74*f3bdbd42SAbhijit Gangurde /** 75*f3bdbd42SAbhijit Gangurde * ionic_queue_length() - Get the current length of the queue 76*f3bdbd42SAbhijit Gangurde * @q: Queue structure 77*f3bdbd42SAbhijit Gangurde * 78*f3bdbd42SAbhijit Gangurde * This is only valid for to-device queues. 79*f3bdbd42SAbhijit Gangurde * 80*f3bdbd42SAbhijit Gangurde * Return: length 81*f3bdbd42SAbhijit Gangurde */ 82*f3bdbd42SAbhijit Gangurde static inline u16 ionic_queue_length(struct ionic_queue *q) 83*f3bdbd42SAbhijit Gangurde { 84*f3bdbd42SAbhijit Gangurde return (q->prod - q->cons) & q->mask; 85*f3bdbd42SAbhijit Gangurde } 86*f3bdbd42SAbhijit Gangurde 87*f3bdbd42SAbhijit Gangurde /** 88*f3bdbd42SAbhijit Gangurde * ionic_queue_length_remaining() - Get the remaining length of the queue 89*f3bdbd42SAbhijit Gangurde * @q: Queue structure 90*f3bdbd42SAbhijit Gangurde * 91*f3bdbd42SAbhijit Gangurde * This is only valid for to-device queues. 92*f3bdbd42SAbhijit Gangurde * 93*f3bdbd42SAbhijit Gangurde * Return: length remaining 94*f3bdbd42SAbhijit Gangurde */ 95*f3bdbd42SAbhijit Gangurde static inline u16 ionic_queue_length_remaining(struct ionic_queue *q) 96*f3bdbd42SAbhijit Gangurde { 97*f3bdbd42SAbhijit Gangurde return q->mask - ionic_queue_length(q); 98*f3bdbd42SAbhijit Gangurde } 99*f3bdbd42SAbhijit Gangurde 100*f3bdbd42SAbhijit Gangurde /** 101*f3bdbd42SAbhijit Gangurde * ionic_queue_full() - Test if queue is full 102*f3bdbd42SAbhijit Gangurde * @q: Queue structure 103*f3bdbd42SAbhijit Gangurde * 104*f3bdbd42SAbhijit Gangurde * This is only valid for to-device queues. 105*f3bdbd42SAbhijit Gangurde * 106*f3bdbd42SAbhijit Gangurde * Return: is full 107*f3bdbd42SAbhijit Gangurde */ 108*f3bdbd42SAbhijit Gangurde static inline bool ionic_queue_full(struct ionic_queue *q) 109*f3bdbd42SAbhijit Gangurde { 110*f3bdbd42SAbhijit Gangurde return q->mask == ionic_queue_length(q); 111*f3bdbd42SAbhijit Gangurde } 112*f3bdbd42SAbhijit Gangurde 113*f3bdbd42SAbhijit Gangurde /** 114*f3bdbd42SAbhijit Gangurde * ionic_color_wrap() - Flip the color if prod is wrapped 115*f3bdbd42SAbhijit Gangurde * @prod: Queue index just after advancing 116*f3bdbd42SAbhijit Gangurde * @color: Queue color just prior to advancing the index 117*f3bdbd42SAbhijit Gangurde * 118*f3bdbd42SAbhijit Gangurde * Return: color after advancing the index 119*f3bdbd42SAbhijit Gangurde */ 120*f3bdbd42SAbhijit Gangurde static inline bool ionic_color_wrap(u16 prod, bool color) 121*f3bdbd42SAbhijit Gangurde { 122*f3bdbd42SAbhijit Gangurde /* logical xor color with (prod == 0) */ 123*f3bdbd42SAbhijit Gangurde return color != (prod == 0); 124*f3bdbd42SAbhijit Gangurde } 125*f3bdbd42SAbhijit Gangurde 126*f3bdbd42SAbhijit Gangurde /** 127*f3bdbd42SAbhijit Gangurde * ionic_queue_at() - Get the element at the given index 128*f3bdbd42SAbhijit Gangurde * @q: Queue structure 129*f3bdbd42SAbhijit Gangurde * @idx: Index in the queue 130*f3bdbd42SAbhijit Gangurde * 131*f3bdbd42SAbhijit Gangurde * The index must be within the bounds of the queue. It is not checked here. 132*f3bdbd42SAbhijit Gangurde * 133*f3bdbd42SAbhijit Gangurde * Return: pointer to element at index 134*f3bdbd42SAbhijit Gangurde */ 135*f3bdbd42SAbhijit Gangurde static inline void *ionic_queue_at(struct ionic_queue *q, u16 idx) 136*f3bdbd42SAbhijit Gangurde { 137*f3bdbd42SAbhijit Gangurde return q->ptr + ((unsigned long)idx << q->stride_log2); 138*f3bdbd42SAbhijit Gangurde } 139*f3bdbd42SAbhijit Gangurde 140*f3bdbd42SAbhijit Gangurde /** 141*f3bdbd42SAbhijit Gangurde * ionic_queue_at_prod() - Get the element at the producer index 142*f3bdbd42SAbhijit Gangurde * @q: Queue structure 143*f3bdbd42SAbhijit Gangurde * 144*f3bdbd42SAbhijit Gangurde * Return: pointer to element at producer index 145*f3bdbd42SAbhijit Gangurde */ 146*f3bdbd42SAbhijit Gangurde static inline void *ionic_queue_at_prod(struct ionic_queue *q) 147*f3bdbd42SAbhijit Gangurde { 148*f3bdbd42SAbhijit Gangurde return ionic_queue_at(q, q->prod); 149*f3bdbd42SAbhijit Gangurde } 150*f3bdbd42SAbhijit Gangurde 151*f3bdbd42SAbhijit Gangurde /** 152*f3bdbd42SAbhijit Gangurde * ionic_queue_at_cons() - Get the element at the consumer index 153*f3bdbd42SAbhijit Gangurde * @q: Queue structure 154*f3bdbd42SAbhijit Gangurde * 155*f3bdbd42SAbhijit Gangurde * Return: pointer to element at consumer index 156*f3bdbd42SAbhijit Gangurde */ 157*f3bdbd42SAbhijit Gangurde static inline void *ionic_queue_at_cons(struct ionic_queue *q) 158*f3bdbd42SAbhijit Gangurde { 159*f3bdbd42SAbhijit Gangurde return ionic_queue_at(q, q->cons); 160*f3bdbd42SAbhijit Gangurde } 161*f3bdbd42SAbhijit Gangurde 162*f3bdbd42SAbhijit Gangurde /** 163*f3bdbd42SAbhijit Gangurde * ionic_queue_next() - Compute the next index 164*f3bdbd42SAbhijit Gangurde * @q: Queue structure 165*f3bdbd42SAbhijit Gangurde * @idx: Index 166*f3bdbd42SAbhijit Gangurde * 167*f3bdbd42SAbhijit Gangurde * Return: next index after idx 168*f3bdbd42SAbhijit Gangurde */ 169*f3bdbd42SAbhijit Gangurde static inline u16 ionic_queue_next(struct ionic_queue *q, u16 idx) 170*f3bdbd42SAbhijit Gangurde { 171*f3bdbd42SAbhijit Gangurde return (idx + 1) & q->mask; 172*f3bdbd42SAbhijit Gangurde } 173*f3bdbd42SAbhijit Gangurde 174*f3bdbd42SAbhijit Gangurde /** 175*f3bdbd42SAbhijit Gangurde * ionic_queue_produce() - Increase the producer index 176*f3bdbd42SAbhijit Gangurde * @q: Queue structure 177*f3bdbd42SAbhijit Gangurde * 178*f3bdbd42SAbhijit Gangurde * Caller must ensure that the queue is not full. It is not checked here. 179*f3bdbd42SAbhijit Gangurde */ 180*f3bdbd42SAbhijit Gangurde static inline void ionic_queue_produce(struct ionic_queue *q) 181*f3bdbd42SAbhijit Gangurde { 182*f3bdbd42SAbhijit Gangurde q->prod = ionic_queue_next(q, q->prod); 183*f3bdbd42SAbhijit Gangurde } 184*f3bdbd42SAbhijit Gangurde 185*f3bdbd42SAbhijit Gangurde /** 186*f3bdbd42SAbhijit Gangurde * ionic_queue_consume() - Increase the consumer index 187*f3bdbd42SAbhijit Gangurde * @q: Queue structure 188*f3bdbd42SAbhijit Gangurde * 189*f3bdbd42SAbhijit Gangurde * Caller must ensure that the queue is not empty. It is not checked here. 190*f3bdbd42SAbhijit Gangurde * 191*f3bdbd42SAbhijit Gangurde * This is only valid for to-device queues. 192*f3bdbd42SAbhijit Gangurde */ 193*f3bdbd42SAbhijit Gangurde static inline void ionic_queue_consume(struct ionic_queue *q) 194*f3bdbd42SAbhijit Gangurde { 195*f3bdbd42SAbhijit Gangurde q->cons = ionic_queue_next(q, q->cons); 196*f3bdbd42SAbhijit Gangurde } 197*f3bdbd42SAbhijit Gangurde 198*f3bdbd42SAbhijit Gangurde /** 199*f3bdbd42SAbhijit Gangurde * ionic_queue_consume_entries() - Increase the consumer index by entries 200*f3bdbd42SAbhijit Gangurde * @q: Queue structure 201*f3bdbd42SAbhijit Gangurde * @entries: Number of entries to increment 202*f3bdbd42SAbhijit Gangurde * 203*f3bdbd42SAbhijit Gangurde * Caller must ensure that the queue is not empty. It is not checked here. 204*f3bdbd42SAbhijit Gangurde * 205*f3bdbd42SAbhijit Gangurde * This is only valid for to-device queues. 206*f3bdbd42SAbhijit Gangurde */ 207*f3bdbd42SAbhijit Gangurde static inline void ionic_queue_consume_entries(struct ionic_queue *q, 208*f3bdbd42SAbhijit Gangurde u16 entries) 209*f3bdbd42SAbhijit Gangurde { 210*f3bdbd42SAbhijit Gangurde q->cons = (q->cons + entries) & q->mask; 211*f3bdbd42SAbhijit Gangurde } 212*f3bdbd42SAbhijit Gangurde 213*f3bdbd42SAbhijit Gangurde /** 214*f3bdbd42SAbhijit Gangurde * ionic_queue_dbell_init() - Initialize doorbell bits for queue id 215*f3bdbd42SAbhijit Gangurde * @q: Queue structure 216*f3bdbd42SAbhijit Gangurde * @qid: Queue identifying number 217*f3bdbd42SAbhijit Gangurde */ 218*f3bdbd42SAbhijit Gangurde static inline void ionic_queue_dbell_init(struct ionic_queue *q, u32 qid) 219*f3bdbd42SAbhijit Gangurde { 220*f3bdbd42SAbhijit Gangurde q->dbell = IONIC_DBELL_QID(qid); 221*f3bdbd42SAbhijit Gangurde } 222*f3bdbd42SAbhijit Gangurde 223*f3bdbd42SAbhijit Gangurde /** 224*f3bdbd42SAbhijit Gangurde * ionic_queue_dbell_val() - Get current doorbell update value 225*f3bdbd42SAbhijit Gangurde * @q: Queue structure 226*f3bdbd42SAbhijit Gangurde * 227*f3bdbd42SAbhijit Gangurde * Return: current doorbell update value 228*f3bdbd42SAbhijit Gangurde */ 229*f3bdbd42SAbhijit Gangurde static inline u64 ionic_queue_dbell_val(struct ionic_queue *q) 230*f3bdbd42SAbhijit Gangurde { 231*f3bdbd42SAbhijit Gangurde return q->dbell | q->prod; 232*f3bdbd42SAbhijit Gangurde } 233*f3bdbd42SAbhijit Gangurde 234*f3bdbd42SAbhijit Gangurde #endif /* _IONIC_QUEUE_H_ */ 235