xref: /dpdk/drivers/bus/dpaa/base/qbman/process.c (revision 68a03efeed657e6e05f281479b33b51102797e15)
1 /* SPDX-License-Identifier: (BSD-3-Clause OR GPL-2.0)
2  *
3  * Copyright 2011-2016 Freescale Semiconductor Inc.
4  * Copyright 2017,2020 NXP
5  *
6  */
7 #include <assert.h>
8 #include <fcntl.h>
9 #include <unistd.h>
10 #include <sys/ioctl.h>
11 #include <rte_ethdev.h>
12 
13 #include "process.h"
14 
15 #include <fsl_usd.h>
16 
17 /* As higher-level drivers will be built on top of this (dma_mem, qbman, ...),
18  * it's preferable that the process driver itself not provide any exported API.
19  * As such, combined with the fact that none of these operations are
20  * performance critical, it is justified to use lazy initialisation, so that's
21  * what the lock is for.
22  */
23 static int fd = -1;
24 static pthread_mutex_t fd_init_lock = PTHREAD_MUTEX_INITIALIZER;
25 
26 static int check_fd(void)
27 {
28 	int ret;
29 
30 	if (fd >= 0)
31 		return 0;
32 	ret = pthread_mutex_lock(&fd_init_lock);
33 	assert(!ret);
34 	/* check again with the lock held */
35 	if (fd < 0)
36 		fd = open(PROCESS_PATH, O_RDWR);
37 	ret = pthread_mutex_unlock(&fd_init_lock);
38 	assert(!ret);
39 	return (fd >= 0) ? 0 : -ENODEV;
40 }
41 
42 #define DPAA_IOCTL_MAGIC 'u'
43 struct dpaa_ioctl_id_alloc {
44 	uint32_t base; /* Return value, the start of the allocated range */
45 	enum dpaa_id_type id_type; /* what kind of resource(s) to allocate */
46 	uint32_t num; /* how many IDs to allocate (and return value) */
47 	uint32_t align; /* must be a power of 2, 0 is treated like 1 */
48 	int partial; /* whether to allow less than 'num' */
49 };
50 
51 struct dpaa_ioctl_id_release {
52 	/* Input; */
53 	enum dpaa_id_type id_type;
54 	uint32_t base;
55 	uint32_t num;
56 };
57 
58 struct dpaa_ioctl_id_reserve {
59 	enum dpaa_id_type id_type;
60 	uint32_t base;
61 	uint32_t num;
62 };
63 
64 #define DPAA_IOCTL_ID_ALLOC \
65 	_IOWR(DPAA_IOCTL_MAGIC, 0x01, struct dpaa_ioctl_id_alloc)
66 #define DPAA_IOCTL_ID_RELEASE \
67 	_IOW(DPAA_IOCTL_MAGIC, 0x02, struct dpaa_ioctl_id_release)
68 #define DPAA_IOCTL_ID_RESERVE \
69 	_IOW(DPAA_IOCTL_MAGIC, 0x0A, struct dpaa_ioctl_id_reserve)
70 
71 int process_alloc(enum dpaa_id_type id_type, uint32_t *base, uint32_t num,
72 		  uint32_t align, int partial)
73 {
74 	struct dpaa_ioctl_id_alloc id = {
75 		.id_type = id_type,
76 		.num = num,
77 		.align = align,
78 		.partial = partial
79 	};
80 	int ret = check_fd();
81 
82 	if (ret)
83 		return ret;
84 	ret = ioctl(fd, DPAA_IOCTL_ID_ALLOC, &id);
85 	if (ret)
86 		return ret;
87 	for (ret = 0; ret < (int)id.num; ret++)
88 		base[ret] = id.base + ret;
89 	return id.num;
90 }
91 
92 void process_release(enum dpaa_id_type id_type, uint32_t base, uint32_t num)
93 {
94 	struct dpaa_ioctl_id_release id = {
95 		.id_type = id_type,
96 		.base = base,
97 		.num = num
98 	};
99 	int ret = check_fd();
100 
101 	if (ret) {
102 		fprintf(stderr, "Process FD failure\n");
103 		return;
104 	}
105 	ret = ioctl(fd, DPAA_IOCTL_ID_RELEASE, &id);
106 	if (ret)
107 		fprintf(stderr, "Process FD ioctl failure type %d base 0x%x num %d\n",
108 			id_type, base, num);
109 }
110 
111 int process_reserve(enum dpaa_id_type id_type, uint32_t base, uint32_t num)
112 {
113 	struct dpaa_ioctl_id_reserve id = {
114 		.id_type = id_type,
115 		.base = base,
116 		.num = num
117 	};
118 	int ret = check_fd();
119 
120 	if (ret)
121 		return ret;
122 	return ioctl(fd, DPAA_IOCTL_ID_RESERVE, &id);
123 }
124 
125 /***************************************/
126 /* Mapping and using QMan/BMan portals */
127 /***************************************/
128 
129 #define DPAA_IOCTL_PORTAL_MAP \
130 	_IOWR(DPAA_IOCTL_MAGIC, 0x07, struct dpaa_ioctl_portal_map)
131 #define DPAA_IOCTL_PORTAL_UNMAP \
132 	_IOW(DPAA_IOCTL_MAGIC, 0x08, struct dpaa_portal_map)
133 
134 int process_portal_map(struct dpaa_ioctl_portal_map *params)
135 {
136 	int ret = check_fd();
137 
138 	if (ret)
139 		return ret;
140 
141 	ret = ioctl(fd, DPAA_IOCTL_PORTAL_MAP, params);
142 	if (ret) {
143 		perror("ioctl(DPAA_IOCTL_PORTAL_MAP)");
144 		return ret;
145 	}
146 	return 0;
147 }
148 
149 int process_portal_unmap(struct dpaa_portal_map *map)
150 {
151 	int ret = check_fd();
152 
153 	if (ret)
154 		return ret;
155 
156 	ret = ioctl(fd, DPAA_IOCTL_PORTAL_UNMAP, map);
157 	if (ret) {
158 		perror("ioctl(DPAA_IOCTL_PORTAL_UNMAP)");
159 		return ret;
160 	}
161 	return 0;
162 }
163 
164 #define DPAA_IOCTL_PORTAL_IRQ_MAP \
165 	_IOW(DPAA_IOCTL_MAGIC, 0x09, struct dpaa_ioctl_irq_map)
166 
167 int process_portal_irq_map(int ifd, struct dpaa_ioctl_irq_map *map)
168 {
169 	map->fd = fd;
170 	return ioctl(ifd, DPAA_IOCTL_PORTAL_IRQ_MAP, map);
171 }
172 
173 int process_portal_irq_unmap(int ifd)
174 {
175 	return close(ifd);
176 }
177 
178 struct dpaa_ioctl_raw_portal {
179 	/* inputs */
180 	enum dpaa_portal_type type; /* Type of portal to allocate */
181 
182 	uint8_t enable_stash; /* set to non zero to turn on stashing */
183 	/* Stashing attributes for the portal */
184 	uint32_t cpu;
185 	uint32_t cache;
186 	uint32_t window;
187 	/* Specifies the stash request queue this portal should use */
188 	uint8_t sdest;
189 
190 	/* Specifes a specific portal index to map or QBMAN_ANY_PORTAL_IDX
191 	 * for don't care.  The portal index will be populated by the
192 	 * driver when the ioctl() successfully completes.
193 	 */
194 	uint32_t index;
195 
196 	/* outputs */
197 	uint64_t cinh;
198 	uint64_t cena;
199 };
200 
201 #define DPAA_IOCTL_ALLOC_RAW_PORTAL \
202 	_IOWR(DPAA_IOCTL_MAGIC, 0x0C, struct dpaa_ioctl_raw_portal)
203 
204 #define DPAA_IOCTL_FREE_RAW_PORTAL \
205 	_IOR(DPAA_IOCTL_MAGIC, 0x0D, struct dpaa_ioctl_raw_portal)
206 
207 static int process_portal_allocate(struct dpaa_ioctl_raw_portal *portal)
208 {
209 	int ret = check_fd();
210 
211 	if (ret)
212 		return ret;
213 
214 	ret = ioctl(fd, DPAA_IOCTL_ALLOC_RAW_PORTAL, portal);
215 	if (ret) {
216 		perror("ioctl(DPAA_IOCTL_ALLOC_RAW_PORTAL)");
217 		return ret;
218 	}
219 	return 0;
220 }
221 
222 static int process_portal_free(struct dpaa_ioctl_raw_portal *portal)
223 {
224 	int ret = check_fd();
225 
226 	if (ret)
227 		return ret;
228 
229 	ret = ioctl(fd, DPAA_IOCTL_FREE_RAW_PORTAL, portal);
230 	if (ret) {
231 		perror("ioctl(DPAA_IOCTL_FREE_RAW_PORTAL)");
232 		return ret;
233 	}
234 	return 0;
235 }
236 
237 int qman_allocate_raw_portal(struct dpaa_raw_portal *portal)
238 {
239 	struct dpaa_ioctl_raw_portal input;
240 	int ret;
241 
242 	input.type = dpaa_portal_qman;
243 	input.index = portal->index;
244 	input.enable_stash = portal->enable_stash;
245 	input.cpu = portal->cpu;
246 	input.cache = portal->cache;
247 	input.window = portal->window;
248 	input.sdest = portal->sdest;
249 
250 	ret =  process_portal_allocate(&input);
251 	if (ret)
252 		return ret;
253 	portal->index = input.index;
254 	portal->cinh = input.cinh;
255 	portal->cena  = input.cena;
256 	return 0;
257 }
258 
259 int qman_free_raw_portal(struct dpaa_raw_portal *portal)
260 {
261 	struct dpaa_ioctl_raw_portal input;
262 
263 	input.type = dpaa_portal_qman;
264 	input.index = portal->index;
265 	input.cinh = portal->cinh;
266 	input.cena = portal->cena;
267 
268 	return process_portal_free(&input);
269 }
270 
271 int bman_allocate_raw_portal(struct dpaa_raw_portal *portal)
272 {
273 	struct dpaa_ioctl_raw_portal input;
274 	int ret;
275 
276 	input.type = dpaa_portal_bman;
277 	input.index = portal->index;
278 	input.enable_stash = 0;
279 
280 	ret =  process_portal_allocate(&input);
281 	if (ret)
282 		return ret;
283 	portal->index = input.index;
284 	portal->cinh = input.cinh;
285 	portal->cena  = input.cena;
286 	return 0;
287 }
288 
289 int bman_free_raw_portal(struct dpaa_raw_portal *portal)
290 {
291 	struct dpaa_ioctl_raw_portal input;
292 
293 	input.type = dpaa_portal_bman;
294 	input.index = portal->index;
295 	input.cinh = portal->cinh;
296 	input.cena = portal->cena;
297 
298 	return process_portal_free(&input);
299 }
300 
301 #define DPAA_IOCTL_ENABLE_LINK_STATUS_INTERRUPT \
302 	_IOW(DPAA_IOCTL_MAGIC, 0x0E, struct usdpaa_ioctl_link_status)
303 
304 #define DPAA_IOCTL_DISABLE_LINK_STATUS_INTERRUPT \
305 	_IOW(DPAA_IOCTL_MAGIC, 0x0F, char*)
306 
307 int dpaa_intr_enable(char *if_name, int efd)
308 {
309 	struct usdpaa_ioctl_link_status args;
310 
311 	int ret = check_fd();
312 
313 	if (ret)
314 		return ret;
315 
316 	args.efd = (uint32_t)efd;
317 	strcpy(args.if_name, if_name);
318 
319 	ret = ioctl(fd, DPAA_IOCTL_ENABLE_LINK_STATUS_INTERRUPT, &args);
320 	if (ret)
321 		return errno;
322 
323 	return 0;
324 }
325 
326 int dpaa_intr_disable(char *if_name)
327 {
328 	int ret = check_fd();
329 
330 	if (ret)
331 		return ret;
332 
333 	ret = ioctl(fd, DPAA_IOCTL_DISABLE_LINK_STATUS_INTERRUPT, &if_name);
334 	if (ret) {
335 		if (errno == EINVAL)
336 			printf("Failed to disable interrupt: Not Supported\n");
337 		else
338 			printf("Failed to disable interrupt\n");
339 		return ret;
340 	}
341 
342 	return 0;
343 }
344 
345 #define DPAA_IOCTL_GET_IOCTL_VERSION \
346 	_IOR(DPAA_IOCTL_MAGIC, 0x14, int)
347 
348 int dpaa_get_ioctl_version_number(void)
349 {
350 	int version_num, ret = check_fd();
351 
352 	if (ret)
353 		return ret;
354 
355 	ret = ioctl(fd, DPAA_IOCTL_GET_IOCTL_VERSION, &version_num);
356 	if (ret) {
357 		if (errno == EINVAL) {
358 			version_num = 1;
359 		} else {
360 			printf("Failed to get ioctl version number\n");
361 			version_num = -1;
362 		}
363 	}
364 
365 	return version_num;
366 }
367 
368 #define DPAA_IOCTL_GET_LINK_STATUS \
369 	_IOWR(DPAA_IOCTL_MAGIC, 0x10, struct usdpaa_ioctl_link_status_args)
370 
371 #define DPAA_IOCTL_GET_LINK_STATUS_OLD \
372 	_IOWR(DPAA_IOCTL_MAGIC, 0x10, struct usdpaa_ioctl_link_status_args_old)
373 
374 
375 int dpaa_get_link_status(char *if_name, struct rte_eth_link *link)
376 {
377 	int ioctl_version, ret = check_fd();
378 
379 	if (ret)
380 		return ret;
381 
382 	ioctl_version = dpaa_get_ioctl_version_number();
383 
384 	if (ioctl_version == 2) {
385 		struct usdpaa_ioctl_link_status_args args;
386 
387 		strcpy(args.if_name, if_name);
388 
389 		ret = ioctl(fd, DPAA_IOCTL_GET_LINK_STATUS, &args);
390 		if (ret) {
391 			printf("Failed to get link status\n");
392 			return ret;
393 		}
394 
395 		link->link_status = args.link_status;
396 		link->link_speed = args.link_speed;
397 		link->link_duplex = args.link_duplex;
398 		link->link_autoneg = args.link_autoneg;
399 	} else {
400 		struct usdpaa_ioctl_link_status_args_old args;
401 
402 		strcpy(args.if_name, if_name);
403 
404 		ret = ioctl(fd, DPAA_IOCTL_GET_LINK_STATUS_OLD, &args);
405 		if (ret) {
406 			if (errno == EINVAL)
407 				printf("Get link status: Not Supported\n");
408 			else
409 				printf("Failed to get link status\n");
410 			return ret;
411 		}
412 
413 		link->link_status = args.link_status;
414 	}
415 
416 	return 0;
417 }
418 
419 #define DPAA_IOCTL_UPDATE_LINK_STATUS \
420 	_IOW(DPAA_IOCTL_MAGIC, 0x11, struct usdpaa_ioctl_update_link_status_args)
421 
422 int dpaa_update_link_status(char *if_name, int link_status)
423 {
424 	struct usdpaa_ioctl_update_link_status_args args;
425 	int ret;
426 
427 	ret = check_fd();
428 	if (ret)
429 		return ret;
430 
431 	strcpy(args.if_name, if_name);
432 	args.link_status = link_status;
433 
434 	ret = ioctl(fd, DPAA_IOCTL_UPDATE_LINK_STATUS, &args);
435 	if (ret) {
436 		if (errno == EINVAL)
437 			printf("Failed to set link status: Not Supported\n");
438 		else
439 			printf("Failed to set link status");
440 		return ret;
441 	}
442 
443 	return 0;
444 }
445 
446 #define DPAA_IOCTL_UPDATE_LINK_SPEED \
447 	_IOW(DPAA_IOCTL_MAGIC, 0x12, struct usdpaa_ioctl_update_link_speed)
448 
449 int dpaa_update_link_speed(char *if_name, int link_speed, int link_duplex)
450 {
451 	struct usdpaa_ioctl_update_link_speed args;
452 	int ret;
453 
454 	ret = check_fd();
455 	if (ret)
456 		return ret;
457 
458 	strcpy(args.if_name, if_name);
459 	args.link_speed = link_speed;
460 	args.link_duplex = link_duplex;
461 
462 	ret = ioctl(fd, DPAA_IOCTL_UPDATE_LINK_SPEED, &args);
463 	if (ret) {
464 		if (errno == EINVAL)
465 			printf("Failed to set link speed: Not Supported\n");
466 		else
467 			printf("Failed to set link speed\n");
468 		return ret;
469 	}
470 
471 	return ret;
472 }
473 
474 #define DPAA_IOCTL_RESTART_LINK_AUTONEG \
475 	_IOW(DPAA_IOCTL_MAGIC, 0x13, char *)
476 
477 int dpaa_restart_link_autoneg(char *if_name)
478 {
479 	int ret = check_fd();
480 
481 	if (ret)
482 		return ret;
483 
484 	ret = ioctl(fd, DPAA_IOCTL_RESTART_LINK_AUTONEG, &if_name);
485 	if (ret) {
486 		if (errno == EINVAL)
487 			printf("Failed to restart autoneg: Not Supported\n");
488 		else
489 			printf("Failed to restart autoneg\n");
490 		return ret;
491 	}
492 
493 	return ret;
494 }
495