Branch data Line data Source code
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 : :
27 : 0 : static int check_fd(void)
28 : : {
29 : : int ret;
30 : :
31 : 0 : ret = pthread_mutex_lock(&fd_init_lock);
32 [ # # ]: 0 : assert(!ret);
33 : :
34 : : /* check again with the lock held */
35 [ # # ]: 0 : if (fd < 0)
36 : 0 : fd = open(PROCESS_PATH, O_RDWR);
37 : :
38 : 0 : ret = pthread_mutex_unlock(&fd_init_lock);
39 [ # # ]: 0 : assert(!ret);
40 : :
41 [ # # ]: 0 : 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 : :
73 : 0 : int process_alloc(enum dpaa_id_type id_type, uint32_t *base, uint32_t num,
74 : : uint32_t align, int partial)
75 : : {
76 : 0 : struct dpaa_ioctl_id_alloc id = {
77 : : .id_type = id_type,
78 : : .num = num,
79 : : .align = align,
80 : : .partial = partial
81 : : };
82 : 0 : int ret = check_fd();
83 : :
84 [ # # ]: 0 : if (ret)
85 : : return ret;
86 : 0 : ret = ioctl(fd, DPAA_IOCTL_ID_ALLOC, &id);
87 [ # # ]: 0 : if (ret)
88 : : return ret;
89 [ # # ]: 0 : for (ret = 0; ret < (int)id.num; ret++)
90 : 0 : base[ret] = id.base + ret;
91 : : return id.num;
92 : : }
93 : :
94 : 0 : void process_release(enum dpaa_id_type id_type, uint32_t base, uint32_t num)
95 : : {
96 : 0 : struct dpaa_ioctl_id_release id = {
97 : : .id_type = id_type,
98 : : .base = base,
99 : : .num = num
100 : : };
101 : 0 : int ret = check_fd();
102 : :
103 [ # # ]: 0 : if (ret) {
104 : 0 : DPAA_BUS_ERR("Process FD failure");
105 : 0 : return;
106 : : }
107 : 0 : ret = ioctl(fd, DPAA_IOCTL_ID_RELEASE, &id);
108 [ # # ]: 0 : if (ret)
109 : 0 : DPAA_BUS_ERR("Process FD ioctl failure type %d base 0x%x num %d",
110 : : id_type, base, num);
111 : : }
112 : :
113 : 0 : int process_reserve(enum dpaa_id_type id_type, uint32_t base, uint32_t num)
114 : : {
115 : 0 : struct dpaa_ioctl_id_reserve id = {
116 : : .id_type = id_type,
117 : : .base = base,
118 : : .num = num
119 : : };
120 : 0 : int ret = check_fd();
121 : :
122 [ # # ]: 0 : if (ret)
123 : : return ret;
124 : 0 : 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 : :
136 : 0 : int process_portal_map(struct dpaa_ioctl_portal_map *params)
137 : : {
138 : 0 : int ret = check_fd();
139 : :
140 [ # # ]: 0 : if (ret)
141 : : return ret;
142 : :
143 : 0 : ret = ioctl(fd, DPAA_IOCTL_PORTAL_MAP, params);
144 [ # # ]: 0 : if (ret) {
145 : 0 : perror("ioctl(DPAA_IOCTL_PORTAL_MAP)");
146 : 0 : return ret;
147 : : }
148 : : return 0;
149 : : }
150 : :
151 : 0 : int process_portal_unmap(struct dpaa_portal_map *map)
152 : : {
153 : 0 : int ret = check_fd();
154 : :
155 [ # # ]: 0 : if (ret)
156 : : return ret;
157 : :
158 : 0 : ret = ioctl(fd, DPAA_IOCTL_PORTAL_UNMAP, map);
159 [ # # ]: 0 : if (ret) {
160 : 0 : perror("ioctl(DPAA_IOCTL_PORTAL_UNMAP)");
161 : 0 : 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 : :
169 : 0 : int process_portal_irq_map(int ifd, struct dpaa_ioctl_irq_map *map)
170 : : {
171 : 0 : map->fd = fd;
172 : 0 : return ioctl(ifd, DPAA_IOCTL_PORTAL_IRQ_MAP, map);
173 : : }
174 : :
175 : 0 : int process_portal_irq_unmap(int ifd)
176 : : {
177 : 0 : 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 : :
209 : 0 : static int process_portal_allocate(struct dpaa_ioctl_raw_portal *portal)
210 : : {
211 : 0 : int ret = check_fd();
212 : :
213 [ # # ]: 0 : if (ret)
214 : : return ret;
215 : :
216 : 0 : ret = ioctl(fd, DPAA_IOCTL_ALLOC_RAW_PORTAL, portal);
217 [ # # ]: 0 : if (ret) {
218 : 0 : perror("ioctl(DPAA_IOCTL_ALLOC_RAW_PORTAL)");
219 : 0 : return ret;
220 : : }
221 : : return 0;
222 : : }
223 : :
224 : 0 : static int process_portal_free(struct dpaa_ioctl_raw_portal *portal)
225 : : {
226 : 0 : int ret = check_fd();
227 : :
228 [ # # ]: 0 : if (ret)
229 : : return ret;
230 : :
231 : 0 : ret = ioctl(fd, DPAA_IOCTL_FREE_RAW_PORTAL, portal);
232 [ # # ]: 0 : if (ret) {
233 : 0 : perror("ioctl(DPAA_IOCTL_FREE_RAW_PORTAL)");
234 : 0 : return ret;
235 : : }
236 : : return 0;
237 : : }
238 : :
239 : 0 : int qman_allocate_raw_portal(struct dpaa_raw_portal *portal)
240 : : {
241 : : struct dpaa_ioctl_raw_portal input;
242 : : int ret;
243 : :
244 : 0 : input.type = dpaa_portal_qman;
245 : 0 : input.index = portal->index;
246 : 0 : input.enable_stash = portal->enable_stash;
247 : 0 : input.cpu = portal->cpu;
248 : 0 : input.cache = portal->cache;
249 : 0 : input.window = portal->window;
250 : 0 : input.sdest = portal->sdest;
251 : :
252 : 0 : ret = process_portal_allocate(&input);
253 [ # # ]: 0 : if (ret)
254 : : return ret;
255 : 0 : portal->index = input.index;
256 : 0 : portal->cinh = input.cinh;
257 : 0 : portal->cena = input.cena;
258 : 0 : return 0;
259 : : }
260 : :
261 : 0 : int qman_free_raw_portal(struct dpaa_raw_portal *portal)
262 : : {
263 : : struct dpaa_ioctl_raw_portal input;
264 : :
265 : 0 : input.type = dpaa_portal_qman;
266 : 0 : input.index = portal->index;
267 : 0 : input.cinh = portal->cinh;
268 : 0 : input.cena = portal->cena;
269 : :
270 : 0 : return process_portal_free(&input);
271 : : }
272 : :
273 : 0 : int bman_allocate_raw_portal(struct dpaa_raw_portal *portal)
274 : : {
275 : : struct dpaa_ioctl_raw_portal input;
276 : : int ret;
277 : :
278 : 0 : input.type = dpaa_portal_bman;
279 : 0 : input.index = portal->index;
280 : 0 : input.enable_stash = 0;
281 : :
282 : 0 : ret = process_portal_allocate(&input);
283 [ # # ]: 0 : if (ret)
284 : : return ret;
285 : 0 : portal->index = input.index;
286 : 0 : portal->cinh = input.cinh;
287 : 0 : portal->cena = input.cena;
288 : 0 : return 0;
289 : : }
290 : :
291 : 0 : int bman_free_raw_portal(struct dpaa_raw_portal *portal)
292 : : {
293 : : struct dpaa_ioctl_raw_portal input;
294 : :
295 : 0 : input.type = dpaa_portal_bman;
296 : 0 : input.index = portal->index;
297 : 0 : input.cinh = portal->cinh;
298 : 0 : input.cena = portal->cena;
299 : :
300 : 0 : 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 : :
309 : 0 : int dpaa_intr_enable(char *if_name, int efd)
310 : : {
311 : : struct usdpaa_ioctl_link_status args;
312 : :
313 : 0 : int ret = check_fd();
314 : :
315 [ # # ]: 0 : if (ret)
316 : : return ret;
317 : :
318 : 0 : args.efd = (uint32_t)efd;
319 : : strcpy(args.if_name, if_name);
320 : :
321 : 0 : ret = ioctl(fd, DPAA_IOCTL_ENABLE_LINK_STATUS_INTERRUPT, &args);
322 [ # # ]: 0 : if (ret)
323 : 0 : return errno;
324 : :
325 : : return 0;
326 : : }
327 : :
328 : 0 : int dpaa_intr_disable(char *if_name)
329 : : {
330 : 0 : int ret = check_fd();
331 : :
332 [ # # ]: 0 : if (ret)
333 : : return ret;
334 : :
335 : 0 : ret = ioctl(fd, DPAA_IOCTL_DISABLE_LINK_STATUS_INTERRUPT, if_name);
336 [ # # ]: 0 : if (ret) {
337 [ # # ]: 0 : if (errno == EINVAL)
338 : 0 : DPAA_BUS_ERR("Failed to disable interrupt: Not Supported");
339 : : else
340 : 0 : DPAA_BUS_ERR("Failed to disable interrupt");
341 : 0 : return ret;
342 : : }
343 : :
344 : : return 0;
345 : : }
346 : :
347 : : #define DPAA_IOCTL_GET_IOCTL_VERSION \
348 : : _IOR(DPAA_IOCTL_MAGIC, 0x14, int)
349 : :
350 : 0 : int dpaa_get_ioctl_version_number(void)
351 : : {
352 : 0 : int version_num, ret = check_fd();
353 : :
354 [ # # ]: 0 : if (ret)
355 : : return ret;
356 : :
357 : 0 : ret = ioctl(fd, DPAA_IOCTL_GET_IOCTL_VERSION, &version_num);
358 [ # # ]: 0 : if (ret) {
359 [ # # ]: 0 : if (errno == EINVAL) {
360 : 0 : version_num = 1;
361 : : } else {
362 : 0 : DPAA_BUS_ERR("Failed to get ioctl version number");
363 : 0 : version_num = -1;
364 : : }
365 : : }
366 : :
367 : 0 : 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 : :
377 : 0 : int dpaa_get_link_status(char *if_name, struct rte_eth_link *link)
378 : : {
379 : 0 : int ioctl_version, ret = check_fd();
380 : :
381 [ # # ]: 0 : if (ret)
382 : : return ret;
383 : :
384 : 0 : ioctl_version = dpaa_get_ioctl_version_number();
385 : :
386 [ # # ]: 0 : if (ioctl_version == 2) {
387 : : struct usdpaa_ioctl_link_status_args args;
388 : :
389 : : strcpy(args.if_name, if_name);
390 : :
391 : 0 : ret = ioctl(fd, DPAA_IOCTL_GET_LINK_STATUS, &args);
392 [ # # ]: 0 : if (ret) {
393 : 0 : DPAA_BUS_ERR("Failed to get link status");
394 : 0 : return ret;
395 : : }
396 : :
397 : 0 : link->link_status = args.link_status;
398 : 0 : link->link_speed = args.link_speed;
399 : 0 : link->link_duplex = args.link_duplex;
400 : 0 : 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 : 0 : ret = ioctl(fd, DPAA_IOCTL_GET_LINK_STATUS_OLD, &args);
407 [ # # ]: 0 : if (ret) {
408 [ # # ]: 0 : if (errno == EINVAL)
409 : 0 : DPAA_BUS_ERR("Get link status: Not Supported");
410 : : else
411 : 0 : DPAA_BUS_ERR("Failed to get link status");
412 : 0 : return ret;
413 : : }
414 : :
415 : 0 : 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 : :
424 : 0 : 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 : 0 : ret = check_fd();
430 [ # # ]: 0 : if (ret)
431 : : return ret;
432 : :
433 : : strcpy(args.if_name, if_name);
434 : 0 : args.link_status = link_status;
435 : :
436 : 0 : ret = ioctl(fd, DPAA_IOCTL_UPDATE_LINK_STATUS, &args);
437 [ # # ]: 0 : if (ret) {
438 [ # # ]: 0 : if (errno == EINVAL)
439 : 0 : DPAA_BUS_ERR("Failed to set link status: Not Supported");
440 : : else
441 : 0 : DPAA_BUS_ERR("Failed to set link status");
442 : 0 : 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 : :
451 : 0 : 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 : 0 : ret = check_fd();
457 [ # # ]: 0 : if (ret)
458 : : return ret;
459 : :
460 : : strcpy(args.if_name, if_name);
461 : 0 : args.link_speed = link_speed;
462 : 0 : args.link_duplex = link_duplex;
463 : :
464 : 0 : ret = ioctl(fd, DPAA_IOCTL_UPDATE_LINK_SPEED, &args);
465 [ # # ]: 0 : if (ret) {
466 [ # # ]: 0 : if (errno == EINVAL)
467 : 0 : DPAA_BUS_ERR("Failed to set link speed: Not Supported");
468 : : else
469 : 0 : DPAA_BUS_ERR("Failed to set link speed");
470 : 0 : 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 : :
479 : 0 : int dpaa_restart_link_autoneg(char *if_name)
480 : : {
481 : 0 : int ret = check_fd();
482 : :
483 [ # # ]: 0 : if (ret)
484 : : return ret;
485 : :
486 : 0 : ret = ioctl(fd, DPAA_IOCTL_RESTART_LINK_AUTONEG, if_name);
487 [ # # ]: 0 : if (ret) {
488 [ # # ]: 0 : if (errno == EINVAL)
489 : 0 : DPAA_BUS_ERR("Failed to restart autoneg: Not Supported");
490 : : else
491 : 0 : DPAA_BUS_ERR("Failed to restart autoneg");
492 : 0 : return ret;
493 : : }
494 : :
495 : : return ret;
496 : : }
|