xref: /f-stack/dpdk/drivers/bus/dpaa/base/qbman/process.c (revision 031be553)
1 /*-
2  * This file is provided under a dual BSD/GPLv2 license. When using or
3  * redistributing this file, you may do so under either license.
4  *
5  *   BSD LICENSE
6  *
7  * Copyright 2011-2016 Freescale Semiconductor Inc.
8  * Copyright 2017 NXP.
9  *
10  * Redistribution and use in source and binary forms, with or without
11  * modification, are permitted provided that the following conditions are met:
12  * * Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  * * Redistributions in binary form must reproduce the above copyright
15  * notice, this list of conditions and the following disclaimer in the
16  * documentation and/or other materials provided with the distribution.
17  * * Neither the name of the above-listed copyright holders nor the
18  * names of any contributors may be used to endorse or promote products
19  * derived from this software without specific prior written permission.
20  *
21  *   GPL LICENSE SUMMARY
22  *
23  * ALTERNATIVELY, this software may be distributed under the terms of the
24  * GNU General Public License ("GPL") as published by the Free Software
25  * Foundation, either version 2 of that License or (at your option) any
26  * later version.
27  *
28  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
32  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38  * POSSIBILITY OF SUCH DAMAGE.
39  */
40 #include <assert.h>
41 #include <fcntl.h>
42 #include <unistd.h>
43 #include <sys/ioctl.h>
44 
45 #include "process.h"
46 
47 #include <fsl_usd.h>
48 
49 /* As higher-level drivers will be built on top of this (dma_mem, qbman, ...),
50  * it's preferable that the process driver itself not provide any exported API.
51  * As such, combined with the fact that none of these operations are
52  * performance critical, it is justified to use lazy initialisation, so that's
53  * what the lock is for.
54  */
55 static int fd = -1;
56 static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
57 
58 static int check_fd(void)
59 {
60 	int ret;
61 
62 	if (fd >= 0)
63 		return 0;
64 	ret = pthread_mutex_lock(&fd_init_lock);
65 	assert(!ret);
66 	/* check again with the lock held */
67 	if (fd < 0)
68 		fd = open(PROCESS_PATH, O_RDWR);
69 	ret = pthread_mutex_unlock(&fd_init_lock);
70 	assert(!ret);
71 	return (fd >= 0) ? 0 : -ENODEV;
72 }
73 
74 #define DPAA_IOCTL_MAGIC 'u'
75 struct dpaa_ioctl_id_alloc {
76 	uint32_t base; /* Return value, the start of the allocated range */
77 	enum dpaa_id_type id_type; /* what kind of resource(s) to allocate */
78 	uint32_t num; /* how many IDs to allocate (and return value) */
79 	uint32_t align; /* must be a power of 2, 0 is treated like 1 */
80 	int partial; /* whether to allow less than 'num' */
81 };
82 
83 struct dpaa_ioctl_id_release {
84 	/* Input; */
85 	enum dpaa_id_type id_type;
86 	uint32_t base;
87 	uint32_t num;
88 };
89 
90 struct dpaa_ioctl_id_reserve {
91 	enum dpaa_id_type id_type;
92 	uint32_t base;
93 	uint32_t num;
94 };
95 
96 #define DPAA_IOCTL_ID_ALLOC \
97 	_IOWR(DPAA_IOCTL_MAGIC, 0x01, struct dpaa_ioctl_id_alloc)
98 #define DPAA_IOCTL_ID_RELEASE \
99 	_IOW(DPAA_IOCTL_MAGIC, 0x02, struct dpaa_ioctl_id_release)
100 #define DPAA_IOCTL_ID_RESERVE \
101 	_IOW(DPAA_IOCTL_MAGIC, 0x0A, struct dpaa_ioctl_id_reserve)
102 
103 int process_alloc(enum dpaa_id_type id_type, uint32_t *base, uint32_t num,
104 		  uint32_t align, int partial)
105 {
106 	struct dpaa_ioctl_id_alloc id = {
107 		.id_type = id_type,
108 		.num = num,
109 		.align = align,
110 		.partial = partial
111 	};
112 	int ret = check_fd();
113 
114 	if (ret)
115 		return ret;
116 	ret = ioctl(fd, DPAA_IOCTL_ID_ALLOC, &id);
117 	if (ret)
118 		return ret;
119 	for (ret = 0; ret < (int)id.num; ret++)
120 		base[ret] = id.base + ret;
121 	return id.num;
122 }
123 
124 void process_release(enum dpaa_id_type id_type, uint32_t base, uint32_t num)
125 {
126 	struct dpaa_ioctl_id_release id = {
127 		.id_type = id_type,
128 		.base = base,
129 		.num = num
130 	};
131 	int ret = check_fd();
132 
133 	if (ret) {
134 		fprintf(stderr, "Process FD failure\n");
135 		return;
136 	}
137 	ret = ioctl(fd, DPAA_IOCTL_ID_RELEASE, &id);
138 	if (ret)
139 		fprintf(stderr, "Process FD ioctl failure type %d base 0x%x num %d\n",
140 			id_type, base, num);
141 }
142 
143 int process_reserve(enum dpaa_id_type id_type, uint32_t base, uint32_t num)
144 {
145 	struct dpaa_ioctl_id_reserve id = {
146 		.id_type = id_type,
147 		.base = base,
148 		.num = num
149 	};
150 	int ret = check_fd();
151 
152 	if (ret)
153 		return ret;
154 	return ioctl(fd, DPAA_IOCTL_ID_RESERVE, &id);
155 }
156 
157 /***************************************/
158 /* Mapping and using QMan/BMan portals */
159 /***************************************/
160 
161 #define DPAA_IOCTL_PORTAL_MAP \
162 	_IOWR(DPAA_IOCTL_MAGIC, 0x07, struct dpaa_ioctl_portal_map)
163 #define DPAA_IOCTL_PORTAL_UNMAP \
164 	_IOW(DPAA_IOCTL_MAGIC, 0x08, struct dpaa_portal_map)
165 
166 int process_portal_map(struct dpaa_ioctl_portal_map *params)
167 {
168 	int ret = check_fd();
169 
170 	if (ret)
171 		return ret;
172 
173 	ret = ioctl(fd, DPAA_IOCTL_PORTAL_MAP, params);
174 	if (ret) {
175 		perror("ioctl(DPAA_IOCTL_PORTAL_MAP)");
176 		return ret;
177 	}
178 	return 0;
179 }
180 
181 int process_portal_unmap(struct dpaa_portal_map *map)
182 {
183 	int ret = check_fd();
184 
185 	if (ret)
186 		return ret;
187 
188 	ret = ioctl(fd, DPAA_IOCTL_PORTAL_UNMAP, map);
189 	if (ret) {
190 		perror("ioctl(DPAA_IOCTL_PORTAL_UNMAP)");
191 		return ret;
192 	}
193 	return 0;
194 }
195 
196 #define DPAA_IOCTL_PORTAL_IRQ_MAP \
197 	_IOW(DPAA_IOCTL_MAGIC, 0x09, struct dpaa_ioctl_irq_map)
198 
199 int process_portal_irq_map(int ifd, struct dpaa_ioctl_irq_map *map)
200 {
201 	map->fd = fd;
202 	return ioctl(ifd, DPAA_IOCTL_PORTAL_IRQ_MAP, map);
203 }
204 
205 int process_portal_irq_unmap(int ifd)
206 {
207 	return close(ifd);
208 }
209 
210 struct dpaa_ioctl_raw_portal {
211 	/* inputs */
212 	enum dpaa_portal_type type; /* Type of portal to allocate */
213 
214 	uint8_t enable_stash; /* set to non zero to turn on stashing */
215 	/* Stashing attributes for the portal */
216 	uint32_t cpu;
217 	uint32_t cache;
218 	uint32_t window;
219 	/* Specifies the stash request queue this portal should use */
220 	uint8_t sdest;
221 
222 	/* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX
223 	 * for don't care.  The portal index will be populated by the
224 	 * driver when the ioctl() successfully completes.
225 	 */
226 	uint32_t index;
227 
228 	/* outputs */
229 	uint64_t cinh;
230 	uint64_t cena;
231 };
232 
233 #define DPAA_IOCTL_ALLOC_RAW_PORTAL \
234 	_IOWR(DPAA_IOCTL_MAGIC, 0x0C, struct dpaa_ioctl_raw_portal)
235 
236 #define DPAA_IOCTL_FREE_RAW_PORTAL \
237 	_IOR(DPAA_IOCTL_MAGIC, 0x0D, struct dpaa_ioctl_raw_portal)
238 
239 static int process_portal_allocate(struct dpaa_ioctl_raw_portal *portal)
240 {
241 	int ret = check_fd();
242 
243 	if (ret)
244 		return ret;
245 
246 	ret = ioctl(fd, DPAA_IOCTL_ALLOC_RAW_PORTAL, portal);
247 	if (ret) {
248 		perror("ioctl(DPAA_IOCTL_ALLOC_RAW_PORTAL)");
249 		return ret;
250 	}
251 	return 0;
252 }
253 
254 static int process_portal_free(struct dpaa_ioctl_raw_portal *portal)
255 {
256 	int ret = check_fd();
257 
258 	if (ret)
259 		return ret;
260 
261 	ret = ioctl(fd, DPAA_IOCTL_FREE_RAW_PORTAL, portal);
262 	if (ret) {
263 		perror("ioctl(DPAA_IOCTL_FREE_RAW_PORTAL)");
264 		return ret;
265 	}
266 	return 0;
267 }
268 
269 int qman_allocate_raw_portal(struct dpaa_raw_portal *portal)
270 {
271 	struct dpaa_ioctl_raw_portal input;
272 	int ret;
273 
274 	input.type = dpaa_portal_qman;
275 	input.index = portal->index;
276 	input.enable_stash = portal->enable_stash;
277 	input.cpu = portal->cpu;
278 	input.cache = portal->cache;
279 	input.window = portal->window;
280 	input.sdest = portal->sdest;
281 
282 	ret =  process_portal_allocate(&input);
283 	if (ret)
284 		return ret;
285 	portal->index = input.index;
286 	portal->cinh = input.cinh;
287 	portal->cena  = input.cena;
288 	return 0;
289 }
290 
291 int qman_free_raw_portal(struct dpaa_raw_portal *portal)
292 {
293 	struct dpaa_ioctl_raw_portal input;
294 
295 	input.type = dpaa_portal_qman;
296 	input.index = portal->index;
297 	input.cinh = portal->cinh;
298 	input.cena = portal->cena;
299 
300 	return process_portal_free(&input);
301 }
302 
303 int bman_allocate_raw_portal(struct dpaa_raw_portal *portal)
304 {
305 	struct dpaa_ioctl_raw_portal input;
306 	int ret;
307 
308 	input.type = dpaa_portal_bman;
309 	input.index = portal->index;
310 	input.enable_stash = 0;
311 
312 	ret =  process_portal_allocate(&input);
313 	if (ret)
314 		return ret;
315 	portal->index = input.index;
316 	portal->cinh = input.cinh;
317 	portal->cena  = input.cena;
318 	return 0;
319 }
320 
321 int bman_free_raw_portal(struct dpaa_raw_portal *portal)
322 {
323 	struct dpaa_ioctl_raw_portal input;
324 
325 	input.type = dpaa_portal_bman;
326 	input.index = portal->index;
327 	input.cinh = portal->cinh;
328 	input.cena = portal->cena;
329 
330 	return process_portal_free(&input);
331 }
332