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