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