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