xref: /linux/drivers/infiniband/hw/ionic/ionic_queue.c (revision f3bdbd42702c6b10ebe627828c76ef51c68e4355)
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 #include <linux/dma-mapping.h>
5*f3bdbd42SAbhijit Gangurde 
6*f3bdbd42SAbhijit Gangurde #include "ionic_queue.h"
7*f3bdbd42SAbhijit Gangurde 
8*f3bdbd42SAbhijit Gangurde int ionic_queue_init(struct ionic_queue *q, struct device *dma_dev,
9*f3bdbd42SAbhijit Gangurde 		     int depth, size_t stride)
10*f3bdbd42SAbhijit Gangurde {
11*f3bdbd42SAbhijit Gangurde 	if (depth < 0 || depth > 0xffff)
12*f3bdbd42SAbhijit Gangurde 		return -EINVAL;
13*f3bdbd42SAbhijit Gangurde 
14*f3bdbd42SAbhijit Gangurde 	if (stride == 0 || stride > 0x10000)
15*f3bdbd42SAbhijit Gangurde 		return -EINVAL;
16*f3bdbd42SAbhijit Gangurde 
17*f3bdbd42SAbhijit Gangurde 	if (depth == 0)
18*f3bdbd42SAbhijit Gangurde 		depth = 1;
19*f3bdbd42SAbhijit Gangurde 
20*f3bdbd42SAbhijit Gangurde 	q->depth_log2 = order_base_2(depth + 1);
21*f3bdbd42SAbhijit Gangurde 	q->stride_log2 = order_base_2(stride);
22*f3bdbd42SAbhijit Gangurde 
23*f3bdbd42SAbhijit Gangurde 	if (q->depth_log2 + q->stride_log2 < PAGE_SHIFT)
24*f3bdbd42SAbhijit Gangurde 		q->depth_log2 = PAGE_SHIFT - q->stride_log2;
25*f3bdbd42SAbhijit Gangurde 
26*f3bdbd42SAbhijit Gangurde 	if (q->depth_log2 > 16 || q->stride_log2 > 16)
27*f3bdbd42SAbhijit Gangurde 		return -EINVAL;
28*f3bdbd42SAbhijit Gangurde 
29*f3bdbd42SAbhijit Gangurde 	q->size = BIT_ULL(q->depth_log2 + q->stride_log2);
30*f3bdbd42SAbhijit Gangurde 	q->mask = BIT(q->depth_log2) - 1;
31*f3bdbd42SAbhijit Gangurde 
32*f3bdbd42SAbhijit Gangurde 	q->ptr = dma_alloc_coherent(dma_dev, q->size, &q->dma, GFP_KERNEL);
33*f3bdbd42SAbhijit Gangurde 	if (!q->ptr)
34*f3bdbd42SAbhijit Gangurde 		return -ENOMEM;
35*f3bdbd42SAbhijit Gangurde 
36*f3bdbd42SAbhijit Gangurde 	/* it will always be page aligned, but just to be sure... */
37*f3bdbd42SAbhijit Gangurde 	if (!PAGE_ALIGNED(q->ptr)) {
38*f3bdbd42SAbhijit Gangurde 		dma_free_coherent(dma_dev, q->size, q->ptr, q->dma);
39*f3bdbd42SAbhijit Gangurde 		return -ENOMEM;
40*f3bdbd42SAbhijit Gangurde 	}
41*f3bdbd42SAbhijit Gangurde 
42*f3bdbd42SAbhijit Gangurde 	q->prod = 0;
43*f3bdbd42SAbhijit Gangurde 	q->cons = 0;
44*f3bdbd42SAbhijit Gangurde 	q->dbell = 0;
45*f3bdbd42SAbhijit Gangurde 
46*f3bdbd42SAbhijit Gangurde 	return 0;
47*f3bdbd42SAbhijit Gangurde }
48*f3bdbd42SAbhijit Gangurde 
49*f3bdbd42SAbhijit Gangurde void ionic_queue_destroy(struct ionic_queue *q, struct device *dma_dev)
50*f3bdbd42SAbhijit Gangurde {
51*f3bdbd42SAbhijit Gangurde 	dma_free_coherent(dma_dev, q->size, q->ptr, q->dma);
52*f3bdbd42SAbhijit Gangurde }
53