xref: /dpdk/drivers/common/nitrox/nitrox_qp.c (revision e99981af34632ecce3bac82d05db97b08308f9b5)
1 /* SPDX-License-Identifier: BSD-3-Clause
2  * Copyright(C) 2019 Marvell International Ltd.
3  */
4 
5 #include <rte_memzone.h>
6 #include <rte_malloc.h>
7 
8 #include "nitrox_qp.h"
9 #include "nitrox_hal.h"
10 #include "nitrox_logs.h"
11 
12 #define MAX_CMD_QLEN 16384
13 #define CMDQ_PKT_IN_ALIGN 16
14 
15 static int
16 nitrox_setup_cmdq(struct nitrox_qp *qp, uint8_t *bar_addr,
17 		  const char *dev_name, uint8_t instr_size, int socket_id)
18 {
19 	char mz_name[RTE_MEMZONE_NAMESIZE];
20 	const struct rte_memzone *mz;
21 	size_t cmdq_size = qp->count * instr_size;
22 	uint64_t offset;
23 	int err = 0;
24 
25 	snprintf(mz_name, sizeof(mz_name), "%s_cmdq_%d", dev_name, qp->qno);
26 	mz = rte_memzone_reserve_aligned(mz_name, cmdq_size, socket_id,
27 					 RTE_MEMZONE_SIZE_HINT_ONLY |
28 					 RTE_MEMZONE_256MB,
29 					 CMDQ_PKT_IN_ALIGN);
30 	if (!mz) {
31 		NITROX_LOG_LINE(ERR, "cmdq memzone reserve failed for %s queue",
32 			   mz_name);
33 		return -ENOMEM;
34 	}
35 
36 	switch (qp->type) {
37 	case NITROX_QUEUE_SE:
38 		offset = NPS_PKT_IN_INSTR_BAOFF_DBELLX(qp->qno);
39 		qp->cmdq.dbell_csr_addr = NITROX_CSR_ADDR(bar_addr, offset);
40 		setup_nps_pkt_input_ring(bar_addr, qp->qno, qp->count,
41 					 mz->iova);
42 		setup_nps_pkt_solicit_output_port(bar_addr, qp->qno);
43 		break;
44 	case NITROX_QUEUE_ZIP:
45 		offset = ZQMQ_DRBLX(qp->qno);
46 		qp->cmdq.dbell_csr_addr = NITROX_CSR_ADDR(bar_addr, offset);
47 		err = setup_zqmq_input_ring(bar_addr, qp->qno, qp->count,
48 					    mz->iova);
49 		break;
50 	default:
51 		NITROX_LOG_LINE(ERR, "Invalid queue type %d", qp->type);
52 		err = -EINVAL;
53 		break;
54 	}
55 
56 	if (err) {
57 		rte_memzone_free(mz);
58 		return err;
59 	}
60 
61 	qp->cmdq.mz = mz;
62 	qp->cmdq.ring = mz->addr;
63 	qp->cmdq.instr_size = instr_size;
64 	return 0;
65 }
66 
67 static int
68 nitrox_setup_ridq(struct nitrox_qp *qp, int socket_id)
69 {
70 	size_t ridq_size = qp->count * sizeof(*qp->ridq);
71 
72 	qp->ridq = rte_zmalloc_socket("nitrox ridq", ridq_size,
73 				   RTE_CACHE_LINE_SIZE,
74 				   socket_id);
75 	if (!qp->ridq) {
76 		NITROX_LOG_LINE(ERR, "Failed to create rid queue");
77 		return -ENOMEM;
78 	}
79 
80 	return 0;
81 }
82 
83 static int
84 nitrox_release_cmdq(struct nitrox_qp *qp, uint8_t *bar_addr)
85 {
86 	int err = 0;
87 
88 	switch (qp->type) {
89 	case NITROX_QUEUE_SE:
90 		nps_pkt_solicited_port_disable(bar_addr, qp->qno);
91 		nps_pkt_input_ring_disable(bar_addr, qp->qno);
92 		break;
93 	case NITROX_QUEUE_ZIP:
94 		err = zqmq_input_ring_disable(bar_addr, qp->qno);
95 		break;
96 	default:
97 		err = -EINVAL;
98 	}
99 
100 	if (err)
101 		return err;
102 
103 	return rte_memzone_free(qp->cmdq.mz);
104 }
105 
106 int
107 nitrox_qp_setup(struct nitrox_qp *qp, uint8_t *bar_addr, const char *dev_name,
108 		uint32_t nb_descriptors, uint8_t instr_size, int socket_id)
109 {
110 	int err;
111 	uint32_t count;
112 
113 	count = rte_align32pow2(nb_descriptors);
114 	if (count > MAX_CMD_QLEN) {
115 		NITROX_LOG_LINE(ERR, "%s: Number of descriptors too big %d,"
116 			   " greater than max queue length %d",
117 			   dev_name, count,
118 			   MAX_CMD_QLEN);
119 		return -EINVAL;
120 	}
121 
122 	qp->bar_addr = bar_addr;
123 	qp->count = count;
124 	qp->head = qp->tail = 0;
125 	rte_atomic_store_explicit(&qp->pending_count, 0,
126 				  rte_memory_order_relaxed);
127 	err = nitrox_setup_cmdq(qp, bar_addr, dev_name, instr_size, socket_id);
128 	if (err)
129 		return err;
130 
131 	err = nitrox_setup_ridq(qp, socket_id);
132 	if (err)
133 		goto ridq_err;
134 
135 	return 0;
136 
137 ridq_err:
138 	nitrox_release_cmdq(qp, bar_addr);
139 	return err;
140 }
141 
142 static void
143 nitrox_release_ridq(struct nitrox_qp *qp)
144 {
145 	rte_free(qp->ridq);
146 }
147 
148 int
149 nitrox_qp_release(struct nitrox_qp *qp, uint8_t *bar_addr)
150 {
151 	nitrox_release_ridq(qp);
152 	return nitrox_release_cmdq(qp, bar_addr);
153 }
154