1 #include <sys/syscall.h>
2 #include <sys/types.h>
3 #include <dirent.h>
4 #include <errno.h>
5 #include <fcntl.h>
6 #include <stdint.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <pthread.h>
10 #include <string.h>
11 #include <unistd.h>
12
13 #include "rmtfs.h"
14
15 #define RPROC_BASE_PATH "/sys/bus/platform/drivers/qcom-q6v5-mss/"
16
17 static pthread_t start_thread;
18 static pthread_t stop_thread;
19 static int rproc_state_fd;
20 static int rproc_pipe[2];
21
rproc_init(void)22 int rproc_init(void)
23 {
24 struct dirent *device_de;
25 struct dirent *rproc_de;
26 int rproc_base_fd;
27 DIR *rproc_dir;
28 DIR *base_dir;
29 int device_fd;
30 int rproc_fd;
31 int base_fd;
32 int ret;
33
34 rproc_state_fd = -1;
35
36 base_fd = open(RPROC_BASE_PATH, O_RDONLY | O_DIRECTORY);
37 if (base_fd < 0)
38 return -1;
39
40 base_dir = fdopendir(base_fd);
41 if (!base_dir) {
42 fprintf(stderr, "failed to open mss driver path\n");
43 close(base_fd);
44 return -1;
45 }
46
47 while (rproc_state_fd < 0 && (device_de = readdir(base_dir)) != NULL) {
48 if (!strcmp(device_de->d_name, ".") ||
49 !strcmp(device_de->d_name, ".."))
50 continue;
51
52 device_fd = openat(base_fd, device_de->d_name, O_RDONLY | O_DIRECTORY);
53 if (device_fd < 0)
54 continue;
55
56 rproc_base_fd = openat(device_fd, "remoteproc", O_RDONLY | O_DIRECTORY);
57 if (rproc_base_fd < 0) {
58 close(device_fd);
59 continue;
60 }
61
62 rproc_dir = fdopendir(rproc_base_fd);
63 while (rproc_state_fd < 0 && (rproc_de = readdir(rproc_dir)) != NULL) {
64 if (!strcmp(rproc_de->d_name, ".") ||
65 !strcmp(rproc_de->d_name, ".."))
66 continue;
67
68 rproc_fd = openat(rproc_base_fd, rproc_de->d_name, O_RDONLY | O_DIRECTORY);
69 if (rproc_fd < 0)
70 continue;
71
72 rproc_state_fd = openat(rproc_fd, "state", O_WRONLY);
73 if (rproc_state_fd < 0) {
74 fprintf(stderr,
75 "unable to open remoteproc \"state\" control file of %s\n",
76 device_de->d_name);
77 }
78
79 close(rproc_fd);
80
81 }
82 closedir(rproc_dir);
83 close(rproc_base_fd);
84 close(device_fd);
85 }
86 closedir(base_dir);
87 close(base_fd);
88
89 if (rproc_state_fd < 0)
90 return -1;
91
92 ret = pipe(rproc_pipe);
93 if (ret < 0) {
94 close(rproc_state_fd);
95 return -1;
96 }
97
98 return rproc_pipe[0];
99 }
100
do_rproc_start(void * unused __unused)101 static void *do_rproc_start(void *unused __unused)
102 {
103 ssize_t ret;
104
105 ret = pwrite(rproc_state_fd, "start", 5, 0);
106 if (ret < 4)
107 fprintf(stderr, "failed to update start state\n");
108
109 return NULL;
110 }
111
rproc_start()112 int rproc_start()
113 {
114 return pthread_create(&start_thread, NULL, do_rproc_start, NULL);
115 }
116
do_rproc_stop(void * unused __unused)117 static void *do_rproc_stop(void *unused __unused)
118 {
119 ssize_t ret;
120
121 ret = pwrite(rproc_state_fd, "stop", 4, 0);
122 if (ret < 4)
123 fprintf(stderr, "failed to update stop state\n");
124
125 ret = write(rproc_pipe[1], "Y", 1);
126 if (ret != 1) {
127 fprintf(stderr, "failed to signal event loop about exit\n");
128 exit(0);
129 }
130
131 return NULL;
132 }
133
rproc_stop(void)134 int rproc_stop(void)
135 {
136 return pthread_create(&stop_thread, NULL, do_rproc_stop, NULL);
137 }
138