~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/power/cpupower/lib/sysfs.c

Version: ~ [ linux-5.5-rc7 ] ~ [ linux-5.4.13 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.97 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.166 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.210 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.210 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.81 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  (C) 2004-2009  Dominik Brodowski <linux@dominikbrodowski.de>
  3  *
  4  *  Licensed under the terms of the GNU GPL License version 2.
  5  */
  6 
  7 #include <stdio.h>
  8 #include <errno.h>
  9 #include <stdlib.h>
 10 #include <string.h>
 11 #include <limits.h>
 12 #include <sys/types.h>
 13 #include <sys/stat.h>
 14 #include <fcntl.h>
 15 #include <unistd.h>
 16 
 17 #include "cpufreq.h"
 18 
 19 #define PATH_TO_CPU "/sys/devices/system/cpu/"
 20 #define MAX_LINE_LEN 4096
 21 #define SYSFS_PATH_MAX 255
 22 
 23 
 24 static unsigned int sysfs_read_file(const char *path, char *buf, size_t buflen)
 25 {
 26         int fd;
 27         ssize_t numread;
 28 
 29         fd = open(path, O_RDONLY);
 30         if (fd == -1)
 31                 return 0;
 32 
 33         numread = read(fd, buf, buflen - 1);
 34         if (numread < 1) {
 35                 close(fd);
 36                 return 0;
 37         }
 38 
 39         buf[numread] = '\0';
 40         close(fd);
 41 
 42         return (unsigned int) numread;
 43 }
 44 
 45 
 46 /* CPUFREQ sysfs access **************************************************/
 47 
 48 /* helper function to read file from /sys into given buffer */
 49 /* fname is a relative path under "cpuX/cpufreq" dir */
 50 static unsigned int sysfs_cpufreq_read_file(unsigned int cpu, const char *fname,
 51                                             char *buf, size_t buflen)
 52 {
 53         char path[SYSFS_PATH_MAX];
 54 
 55         snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
 56                          cpu, fname);
 57         return sysfs_read_file(path, buf, buflen);
 58 }
 59 
 60 /* helper function to write a new value to a /sys file */
 61 /* fname is a relative path under "cpuX/cpufreq" dir */
 62 static unsigned int sysfs_cpufreq_write_file(unsigned int cpu,
 63                                              const char *fname,
 64                                              const char *value, size_t len)
 65 {
 66         char path[SYSFS_PATH_MAX];
 67         int fd;
 68         ssize_t numwrite;
 69 
 70         snprintf(path, sizeof(path), PATH_TO_CPU "cpu%u/cpufreq/%s",
 71                          cpu, fname);
 72 
 73         fd = open(path, O_WRONLY);
 74         if (fd == -1)
 75                 return 0;
 76 
 77         numwrite = write(fd, value, len);
 78         if (numwrite < 1) {
 79                 close(fd);
 80                 return 0;
 81         }
 82 
 83         close(fd);
 84 
 85         return (unsigned int) numwrite;
 86 }
 87 
 88 /* read access to files which contain one numeric value */
 89 
 90 enum cpufreq_value {
 91         CPUINFO_CUR_FREQ,
 92         CPUINFO_MIN_FREQ,
 93         CPUINFO_MAX_FREQ,
 94         CPUINFO_LATENCY,
 95         SCALING_CUR_FREQ,
 96         SCALING_MIN_FREQ,
 97         SCALING_MAX_FREQ,
 98         STATS_NUM_TRANSITIONS,
 99         MAX_CPUFREQ_VALUE_READ_FILES
100 };
101 
102 static const char *cpufreq_value_files[MAX_CPUFREQ_VALUE_READ_FILES] = {
103         [CPUINFO_CUR_FREQ] = "cpuinfo_cur_freq",
104         [CPUINFO_MIN_FREQ] = "cpuinfo_min_freq",
105         [CPUINFO_MAX_FREQ] = "cpuinfo_max_freq",
106         [CPUINFO_LATENCY]  = "cpuinfo_transition_latency",
107         [SCALING_CUR_FREQ] = "scaling_cur_freq",
108         [SCALING_MIN_FREQ] = "scaling_min_freq",
109         [SCALING_MAX_FREQ] = "scaling_max_freq",
110         [STATS_NUM_TRANSITIONS] = "stats/total_trans"
111 };
112 
113 
114 static unsigned long sysfs_cpufreq_get_one_value(unsigned int cpu,
115                                                  enum cpufreq_value which)
116 {
117         unsigned long value;
118         unsigned int len;
119         char linebuf[MAX_LINE_LEN];
120         char *endp;
121 
122         if (which >= MAX_CPUFREQ_VALUE_READ_FILES)
123                 return 0;
124 
125         len = sysfs_cpufreq_read_file(cpu, cpufreq_value_files[which],
126                                 linebuf, sizeof(linebuf));
127 
128         if (len == 0)
129                 return 0;
130 
131         value = strtoul(linebuf, &endp, 0);
132 
133         if (endp == linebuf || errno == ERANGE)
134                 return 0;
135 
136         return value;
137 }
138 
139 /* read access to files which contain one string */
140 
141 enum cpufreq_string {
142         SCALING_DRIVER,
143         SCALING_GOVERNOR,
144         MAX_CPUFREQ_STRING_FILES
145 };
146 
147 static const char *cpufreq_string_files[MAX_CPUFREQ_STRING_FILES] = {
148         [SCALING_DRIVER] = "scaling_driver",
149         [SCALING_GOVERNOR] = "scaling_governor",
150 };
151 
152 
153 static char *sysfs_cpufreq_get_one_string(unsigned int cpu,
154                                            enum cpufreq_string which)
155 {
156         char linebuf[MAX_LINE_LEN];
157         char *result;
158         unsigned int len;
159 
160         if (which >= MAX_CPUFREQ_STRING_FILES)
161                 return NULL;
162 
163         len = sysfs_cpufreq_read_file(cpu, cpufreq_string_files[which],
164                                 linebuf, sizeof(linebuf));
165         if (len == 0)
166                 return NULL;
167 
168         result = strdup(linebuf);
169         if (result == NULL)
170                 return NULL;
171 
172         if (result[strlen(result) - 1] == '\n')
173                 result[strlen(result) - 1] = '\0';
174 
175         return result;
176 }
177 
178 /* write access */
179 
180 enum cpufreq_write {
181         WRITE_SCALING_MIN_FREQ,
182         WRITE_SCALING_MAX_FREQ,
183         WRITE_SCALING_GOVERNOR,
184         WRITE_SCALING_SET_SPEED,
185         MAX_CPUFREQ_WRITE_FILES
186 };
187 
188 static const char *cpufreq_write_files[MAX_CPUFREQ_WRITE_FILES] = {
189         [WRITE_SCALING_MIN_FREQ] = "scaling_min_freq",
190         [WRITE_SCALING_MAX_FREQ] = "scaling_max_freq",
191         [WRITE_SCALING_GOVERNOR] = "scaling_governor",
192         [WRITE_SCALING_SET_SPEED] = "scaling_setspeed",
193 };
194 
195 static int sysfs_cpufreq_write_one_value(unsigned int cpu,
196                                          enum cpufreq_write which,
197                                          const char *new_value, size_t len)
198 {
199         if (which >= MAX_CPUFREQ_WRITE_FILES)
200                 return 0;
201 
202         if (sysfs_cpufreq_write_file(cpu, cpufreq_write_files[which],
203                                         new_value, len) != len)
204                 return -ENODEV;
205 
206         return 0;
207 };
208 
209 unsigned long sysfs_get_freq_kernel(unsigned int cpu)
210 {
211         return sysfs_cpufreq_get_one_value(cpu, SCALING_CUR_FREQ);
212 }
213 
214 unsigned long sysfs_get_freq_hardware(unsigned int cpu)
215 {
216         return sysfs_cpufreq_get_one_value(cpu, CPUINFO_CUR_FREQ);
217 }
218 
219 unsigned long sysfs_get_freq_transition_latency(unsigned int cpu)
220 {
221         return sysfs_cpufreq_get_one_value(cpu, CPUINFO_LATENCY);
222 }
223 
224 int sysfs_get_freq_hardware_limits(unsigned int cpu,
225                               unsigned long *min,
226                               unsigned long *max)
227 {
228         if ((!min) || (!max))
229                 return -EINVAL;
230 
231         *min = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MIN_FREQ);
232         if (!*min)
233                 return -ENODEV;
234 
235         *max = sysfs_cpufreq_get_one_value(cpu, CPUINFO_MAX_FREQ);
236         if (!*max)
237                 return -ENODEV;
238 
239         return 0;
240 }
241 
242 char *sysfs_get_freq_driver(unsigned int cpu)
243 {
244         return sysfs_cpufreq_get_one_string(cpu, SCALING_DRIVER);
245 }
246 
247 struct cpufreq_policy *sysfs_get_freq_policy(unsigned int cpu)
248 {
249         struct cpufreq_policy *policy;
250 
251         policy = malloc(sizeof(struct cpufreq_policy));
252         if (!policy)
253                 return NULL;
254 
255         policy->governor = sysfs_cpufreq_get_one_string(cpu, SCALING_GOVERNOR);
256         if (!policy->governor) {
257                 free(policy);
258                 return NULL;
259         }
260         policy->min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
261         policy->max = sysfs_cpufreq_get_one_value(cpu, SCALING_MAX_FREQ);
262         if ((!policy->min) || (!policy->max)) {
263                 free(policy->governor);
264                 free(policy);
265                 return NULL;
266         }
267 
268         return policy;
269 }
270 
271 struct cpufreq_available_governors *
272 sysfs_get_freq_available_governors(unsigned int cpu) {
273         struct cpufreq_available_governors *first = NULL;
274         struct cpufreq_available_governors *current = NULL;
275         char linebuf[MAX_LINE_LEN];
276         unsigned int pos, i;
277         unsigned int len;
278 
279         len = sysfs_cpufreq_read_file(cpu, "scaling_available_governors",
280                                 linebuf, sizeof(linebuf));
281         if (len == 0)
282                 return NULL;
283 
284         pos = 0;
285         for (i = 0; i < len; i++) {
286                 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
287                         if (i - pos < 2)
288                                 continue;
289                         if (current) {
290                                 current->next = malloc(sizeof(*current));
291                                 if (!current->next)
292                                         goto error_out;
293                                 current = current->next;
294                         } else {
295                                 first = malloc(sizeof(*first));
296                                 if (!first)
297                                         goto error_out;
298                                 current = first;
299                         }
300                         current->first = first;
301                         current->next = NULL;
302 
303                         current->governor = malloc(i - pos + 1);
304                         if (!current->governor)
305                                 goto error_out;
306 
307                         memcpy(current->governor, linebuf + pos, i - pos);
308                         current->governor[i - pos] = '\0';
309                         pos = i + 1;
310                 }
311         }
312 
313         return first;
314 
315  error_out:
316         while (first) {
317                 current = first->next;
318                 if (first->governor)
319                         free(first->governor);
320                 free(first);
321                 first = current;
322         }
323         return NULL;
324 }
325 
326 
327 struct cpufreq_available_frequencies *
328 sysfs_get_available_frequencies(unsigned int cpu) {
329         struct cpufreq_available_frequencies *first = NULL;
330         struct cpufreq_available_frequencies *current = NULL;
331         char one_value[SYSFS_PATH_MAX];
332         char linebuf[MAX_LINE_LEN];
333         unsigned int pos, i;
334         unsigned int len;
335 
336         len = sysfs_cpufreq_read_file(cpu, "scaling_available_frequencies",
337                                 linebuf, sizeof(linebuf));
338         if (len == 0)
339                 return NULL;
340 
341         pos = 0;
342         for (i = 0; i < len; i++) {
343                 if (linebuf[i] == ' ' || linebuf[i] == '\n') {
344                         if (i - pos < 2)
345                                 continue;
346                         if (i - pos >= SYSFS_PATH_MAX)
347                                 goto error_out;
348                         if (current) {
349                                 current->next = malloc(sizeof(*current));
350                                 if (!current->next)
351                                         goto error_out;
352                                 current = current->next;
353                         } else {
354                                 first = malloc(sizeof(*first));
355                                 if (!first)
356                                         goto error_out;
357                                 current = first;
358                         }
359                         current->first = first;
360                         current->next = NULL;
361 
362                         memcpy(one_value, linebuf + pos, i - pos);
363                         one_value[i - pos] = '\0';
364                         if (sscanf(one_value, "%lu", &current->frequency) != 1)
365                                 goto error_out;
366 
367                         pos = i + 1;
368                 }
369         }
370 
371         return first;
372 
373  error_out:
374         while (first) {
375                 current = first->next;
376                 free(first);
377                 first = current;
378         }
379         return NULL;
380 }
381 
382 static struct cpufreq_affected_cpus *sysfs_get_cpu_list(unsigned int cpu,
383                                                         const char *file)
384 {
385         struct cpufreq_affected_cpus *first = NULL;
386         struct cpufreq_affected_cpus *current = NULL;
387         char one_value[SYSFS_PATH_MAX];
388         char linebuf[MAX_LINE_LEN];
389         unsigned int pos, i;
390         unsigned int len;
391 
392         len = sysfs_cpufreq_read_file(cpu, file, linebuf, sizeof(linebuf));
393         if (len == 0)
394                 return NULL;
395 
396         pos = 0;
397         for (i = 0; i < len; i++) {
398                 if (i == len || linebuf[i] == ' ' || linebuf[i] == '\n') {
399                         if (i - pos  < 1)
400                                 continue;
401                         if (i - pos >= SYSFS_PATH_MAX)
402                                 goto error_out;
403                         if (current) {
404                                 current->next = malloc(sizeof(*current));
405                                 if (!current->next)
406                                         goto error_out;
407                                 current = current->next;
408                         } else {
409                                 first = malloc(sizeof(*first));
410                                 if (!first)
411                                         goto error_out;
412                                 current = first;
413                         }
414                         current->first = first;
415                         current->next = NULL;
416 
417                         memcpy(one_value, linebuf + pos, i - pos);
418                         one_value[i - pos] = '\0';
419 
420                         if (sscanf(one_value, "%u", &current->cpu) != 1)
421                                 goto error_out;
422 
423                         pos = i + 1;
424                 }
425         }
426 
427         return first;
428 
429  error_out:
430         while (first) {
431                 current = first->next;
432                 free(first);
433                 first = current;
434         }
435         return NULL;
436 }
437 
438 struct cpufreq_affected_cpus *sysfs_get_freq_affected_cpus(unsigned int cpu)
439 {
440         return sysfs_get_cpu_list(cpu, "affected_cpus");
441 }
442 
443 struct cpufreq_affected_cpus *sysfs_get_freq_related_cpus(unsigned int cpu)
444 {
445         return sysfs_get_cpu_list(cpu, "related_cpus");
446 }
447 
448 struct cpufreq_stats *sysfs_get_freq_stats(unsigned int cpu,
449                                         unsigned long long *total_time) {
450         struct cpufreq_stats *first = NULL;
451         struct cpufreq_stats *current = NULL;
452         char one_value[SYSFS_PATH_MAX];
453         char linebuf[MAX_LINE_LEN];
454         unsigned int pos, i;
455         unsigned int len;
456 
457         len = sysfs_cpufreq_read_file(cpu, "stats/time_in_state",
458                                 linebuf, sizeof(linebuf));
459         if (len == 0)
460                 return NULL;
461 
462         *total_time = 0;
463         pos = 0;
464         for (i = 0; i < len; i++) {
465                 if (i == strlen(linebuf) || linebuf[i] == '\n') {
466                         if (i - pos < 2)
467                                 continue;
468                         if ((i - pos) >= SYSFS_PATH_MAX)
469                                 goto error_out;
470                         if (current) {
471                                 current->next = malloc(sizeof(*current));
472                                 if (!current->next)
473                                         goto error_out;
474                                 current = current->next;
475                         } else {
476                                 first = malloc(sizeof(*first));
477                                 if (!first)
478                                         goto error_out;
479                                 current = first;
480                         }
481                         current->first = first;
482                         current->next = NULL;
483 
484                         memcpy(one_value, linebuf + pos, i - pos);
485                         one_value[i - pos] = '\0';
486                         if (sscanf(one_value, "%lu %llu",
487                                         &current->frequency,
488                                         &current->time_in_state) != 2)
489                                 goto error_out;
490 
491                         *total_time = *total_time + current->time_in_state;
492                         pos = i + 1;
493                 }
494         }
495 
496         return first;
497 
498  error_out:
499         while (first) {
500                 current = first->next;
501                 free(first);
502                 first = current;
503         }
504         return NULL;
505 }
506 
507 unsigned long sysfs_get_freq_transitions(unsigned int cpu)
508 {
509         return sysfs_cpufreq_get_one_value(cpu, STATS_NUM_TRANSITIONS);
510 }
511 
512 static int verify_gov(char *new_gov, char *passed_gov)
513 {
514         unsigned int i, j = 0;
515 
516         if (!passed_gov || (strlen(passed_gov) > 19))
517                 return -EINVAL;
518 
519         strncpy(new_gov, passed_gov, 20);
520         for (i = 0; i < 20; i++) {
521                 if (j) {
522                         new_gov[i] = '\0';
523                         continue;
524                 }
525                 if ((new_gov[i] >= 'a') && (new_gov[i] <= 'z'))
526                         continue;
527 
528                 if ((new_gov[i] >= 'A') && (new_gov[i] <= 'Z'))
529                         continue;
530 
531                 if (new_gov[i] == '-')
532                         continue;
533 
534                 if (new_gov[i] == '_')
535                         continue;
536 
537                 if (new_gov[i] == '\0') {
538                         j = 1;
539                         continue;
540                 }
541                 return -EINVAL;
542         }
543         new_gov[19] = '\0';
544         return 0;
545 }
546 
547 int sysfs_modify_freq_policy_governor(unsigned int cpu, char *governor)
548 {
549         char new_gov[SYSFS_PATH_MAX];
550 
551         if (!governor)
552                 return -EINVAL;
553 
554         if (verify_gov(new_gov, governor))
555                 return -EINVAL;
556 
557         return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
558                                              new_gov, strlen(new_gov));
559 };
560 
561 int sysfs_modify_freq_policy_max(unsigned int cpu, unsigned long max_freq)
562 {
563         char value[SYSFS_PATH_MAX];
564 
565         snprintf(value, SYSFS_PATH_MAX, "%lu", max_freq);
566 
567         return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
568                                              value, strlen(value));
569 };
570 
571 
572 int sysfs_modify_freq_policy_min(unsigned int cpu, unsigned long min_freq)
573 {
574         char value[SYSFS_PATH_MAX];
575 
576         snprintf(value, SYSFS_PATH_MAX, "%lu", min_freq);
577 
578         return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ,
579                                              value, strlen(value));
580 };
581 
582 
583 int sysfs_set_freq_policy(unsigned int cpu, struct cpufreq_policy *policy)
584 {
585         char min[SYSFS_PATH_MAX];
586         char max[SYSFS_PATH_MAX];
587         char gov[SYSFS_PATH_MAX];
588         int ret;
589         unsigned long old_min;
590         int write_max_first;
591 
592         if (!policy || !(policy->governor))
593                 return -EINVAL;
594 
595         if (policy->max < policy->min)
596                 return -EINVAL;
597 
598         if (verify_gov(gov, policy->governor))
599                 return -EINVAL;
600 
601         snprintf(min, SYSFS_PATH_MAX, "%lu", policy->min);
602         snprintf(max, SYSFS_PATH_MAX, "%lu", policy->max);
603 
604         old_min = sysfs_cpufreq_get_one_value(cpu, SCALING_MIN_FREQ);
605         write_max_first = (old_min && (policy->max < old_min) ? 0 : 1);
606 
607         if (write_max_first) {
608                 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
609                                                     max, strlen(max));
610                 if (ret)
611                         return ret;
612         }
613 
614         ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MIN_FREQ, min,
615                                             strlen(min));
616         if (ret)
617                 return ret;
618 
619         if (!write_max_first) {
620                 ret = sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_MAX_FREQ,
621                                                     max, strlen(max));
622                 if (ret)
623                         return ret;
624         }
625 
626         return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_GOVERNOR,
627                                              gov, strlen(gov));
628 }
629 
630 int sysfs_set_frequency(unsigned int cpu, unsigned long target_frequency)
631 {
632         struct cpufreq_policy *pol = sysfs_get_freq_policy(cpu);
633         char userspace_gov[] = "userspace";
634         char freq[SYSFS_PATH_MAX];
635         int ret;
636 
637         if (!pol)
638                 return -ENODEV;
639 
640         if (strncmp(pol->governor, userspace_gov, 9) != 0) {
641                 ret = sysfs_modify_freq_policy_governor(cpu, userspace_gov);
642                 if (ret) {
643                         cpufreq_put_policy(pol);
644                         return ret;
645                 }
646         }
647 
648         cpufreq_put_policy(pol);
649 
650         snprintf(freq, SYSFS_PATH_MAX, "%lu", target_frequency);
651 
652         return sysfs_cpufreq_write_one_value(cpu, WRITE_SCALING_SET_SPEED,
653                                              freq, strlen(freq));
654 }
655 
656 /* CPUFREQ sysfs access **************************************************/
657 
658 /* General sysfs access **************************************************/
659 int sysfs_cpu_exists(unsigned int cpu)
660 {
661         char file[SYSFS_PATH_MAX];
662         struct stat statbuf;
663 
664         snprintf(file, SYSFS_PATH_MAX, PATH_TO_CPU "cpu%u/", cpu);
665 
666         if (stat(file, &statbuf) != 0)
667                 return -ENOSYS;
668 
669         return S_ISDIR(statbuf.st_mode) ? 0 : -ENOSYS;
670 }
671 
672 /* General sysfs access **************************************************/
673 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp