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
check_fd(void)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
process_alloc(enum dpaa_id_type id_type,uint32_t * base,uint32_t num,uint32_t align,int partial)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
process_release(enum dpaa_id_type id_type,uint32_t base,uint32_t num)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
process_reserve(enum dpaa_id_type id_type,uint32_t base,uint32_t num)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
process_portal_map(struct dpaa_ioctl_portal_map * params)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
process_portal_unmap(struct dpaa_portal_map * map)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
process_portal_irq_map(int ifd,struct dpaa_ioctl_irq_map * map)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
process_portal_irq_unmap(int ifd)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
process_portal_allocate(struct dpaa_ioctl_raw_portal * portal)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
process_portal_free(struct dpaa_ioctl_raw_portal * portal)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
qman_allocate_raw_portal(struct dpaa_raw_portal * portal)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
qman_free_raw_portal(struct dpaa_raw_portal * portal)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
bman_allocate_raw_portal(struct dpaa_raw_portal * portal)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
bman_free_raw_portal(struct dpaa_raw_portal * portal)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
dpaa_intr_enable(char * if_name,int efd)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
dpaa_intr_disable(char * if_name)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
dpaa_get_ioctl_version_number(void)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
dpaa_get_link_status(char * if_name,struct rte_eth_link * link)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
dpaa_update_link_status(char * if_name,int link_status)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
dpaa_update_link_speed(char * if_name,int link_speed,int link_duplex)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
dpaa_restart_link_autoneg(char * if_name)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