forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-10 cde9070d9970eef1f7ec2360586c802a16230ad8
kernel/tools/perf/arch/arm/util/cs-etm.c
....@@ -5,40 +5,190 @@
55 */
66
77 #include <api/fs/fs.h>
8
+#include <linux/bits.h>
89 #include <linux/bitops.h>
910 #include <linux/compiler.h>
1011 #include <linux/coresight-pmu.h>
1112 #include <linux/kernel.h>
1213 #include <linux/log2.h>
14
+#include <linux/string.h>
1315 #include <linux/types.h>
16
+#include <linux/zalloc.h>
1417
1518 #include "cs-etm.h"
16
-#include "../../perf.h"
19
+#include "../../util/debug.h"
20
+#include "../../util/record.h"
1721 #include "../../util/auxtrace.h"
1822 #include "../../util/cpumap.h"
23
+#include "../../util/event.h"
1924 #include "../../util/evlist.h"
2025 #include "../../util/evsel.h"
26
+#include "../../util/perf_api_probe.h"
27
+#include "../../util/evsel_config.h"
2128 #include "../../util/pmu.h"
22
-#include "../../util/thread_map.h"
2329 #include "../../util/cs-etm.h"
30
+#include <internal/lib.h> // page_size
31
+#include "../../util/session.h"
2432
33
+#include <errno.h>
2534 #include <stdlib.h>
2635 #include <sys/stat.h>
27
-
28
-#define ENABLE_SINK_MAX 128
29
-#define CS_BUS_DEVICE_PATH "/bus/coresight/devices/"
3036
3137 struct cs_etm_recording {
3238 struct auxtrace_record itr;
3339 struct perf_pmu *cs_etm_pmu;
34
- struct perf_evlist *evlist;
40
+ struct evlist *evlist;
3541 int wrapped_cnt;
3642 bool *wrapped;
3743 bool snapshot_mode;
3844 size_t snapshot_size;
3945 };
4046
47
+static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX] = {
48
+ [CS_ETM_ETMCCER] = "mgmt/etmccer",
49
+ [CS_ETM_ETMIDR] = "mgmt/etmidr",
50
+};
51
+
52
+static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = {
53
+ [CS_ETMV4_TRCIDR0] = "trcidr/trcidr0",
54
+ [CS_ETMV4_TRCIDR1] = "trcidr/trcidr1",
55
+ [CS_ETMV4_TRCIDR2] = "trcidr/trcidr2",
56
+ [CS_ETMV4_TRCIDR8] = "trcidr/trcidr8",
57
+ [CS_ETMV4_TRCAUTHSTATUS] = "mgmt/trcauthstatus",
58
+};
59
+
4160 static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu);
61
+
62
+static int cs_etm_set_context_id(struct auxtrace_record *itr,
63
+ struct evsel *evsel, int cpu)
64
+{
65
+ struct cs_etm_recording *ptr;
66
+ struct perf_pmu *cs_etm_pmu;
67
+ char path[PATH_MAX];
68
+ int err = -EINVAL;
69
+ u32 val;
70
+
71
+ ptr = container_of(itr, struct cs_etm_recording, itr);
72
+ cs_etm_pmu = ptr->cs_etm_pmu;
73
+
74
+ if (!cs_etm_is_etmv4(itr, cpu))
75
+ goto out;
76
+
77
+ /* Get a handle on TRCIRD2 */
78
+ snprintf(path, PATH_MAX, "cpu%d/%s",
79
+ cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR2]);
80
+ err = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
81
+
82
+ /* There was a problem reading the file, bailing out */
83
+ if (err != 1) {
84
+ pr_err("%s: can't read file %s\n",
85
+ CORESIGHT_ETM_PMU_NAME, path);
86
+ goto out;
87
+ }
88
+
89
+ /*
90
+ * TRCIDR2.CIDSIZE, bit [9-5], indicates whether contextID tracing
91
+ * is supported:
92
+ * 0b00000 Context ID tracing is not supported.
93
+ * 0b00100 Maximum of 32-bit Context ID size.
94
+ * All other values are reserved.
95
+ */
96
+ val = BMVAL(val, 5, 9);
97
+ if (!val || val != 0x4) {
98
+ err = -EINVAL;
99
+ goto out;
100
+ }
101
+
102
+ /* All good, let the kernel know */
103
+ evsel->core.attr.config |= (1 << ETM_OPT_CTXTID);
104
+ err = 0;
105
+
106
+out:
107
+
108
+ return err;
109
+}
110
+
111
+static int cs_etm_set_timestamp(struct auxtrace_record *itr,
112
+ struct evsel *evsel, int cpu)
113
+{
114
+ struct cs_etm_recording *ptr;
115
+ struct perf_pmu *cs_etm_pmu;
116
+ char path[PATH_MAX];
117
+ int err = -EINVAL;
118
+ u32 val;
119
+
120
+ ptr = container_of(itr, struct cs_etm_recording, itr);
121
+ cs_etm_pmu = ptr->cs_etm_pmu;
122
+
123
+ if (!cs_etm_is_etmv4(itr, cpu))
124
+ goto out;
125
+
126
+ /* Get a handle on TRCIRD0 */
127
+ snprintf(path, PATH_MAX, "cpu%d/%s",
128
+ cpu, metadata_etmv4_ro[CS_ETMV4_TRCIDR0]);
129
+ err = perf_pmu__scan_file(cs_etm_pmu, path, "%x", &val);
130
+
131
+ /* There was a problem reading the file, bailing out */
132
+ if (err != 1) {
133
+ pr_err("%s: can't read file %s\n",
134
+ CORESIGHT_ETM_PMU_NAME, path);
135
+ goto out;
136
+ }
137
+
138
+ /*
139
+ * TRCIDR0.TSSIZE, bit [28-24], indicates whether global timestamping
140
+ * is supported:
141
+ * 0b00000 Global timestamping is not implemented
142
+ * 0b00110 Implementation supports a maximum timestamp of 48bits.
143
+ * 0b01000 Implementation supports a maximum timestamp of 64bits.
144
+ */
145
+ val &= GENMASK(28, 24);
146
+ if (!val) {
147
+ err = -EINVAL;
148
+ goto out;
149
+ }
150
+
151
+ /* All good, let the kernel know */
152
+ evsel->core.attr.config |= (1 << ETM_OPT_TS);
153
+ err = 0;
154
+
155
+out:
156
+ return err;
157
+}
158
+
159
+static int cs_etm_set_option(struct auxtrace_record *itr,
160
+ struct evsel *evsel, u32 option)
161
+{
162
+ int i, err = -EINVAL;
163
+ struct perf_cpu_map *event_cpus = evsel->evlist->core.cpus;
164
+ struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
165
+
166
+ /* Set option of each CPU we have */
167
+ for (i = 0; i < cpu__max_cpu(); i++) {
168
+ if (!cpu_map__has(event_cpus, i) ||
169
+ !cpu_map__has(online_cpus, i))
170
+ continue;
171
+
172
+ if (option & ETM_OPT_CTXTID) {
173
+ err = cs_etm_set_context_id(itr, evsel, i);
174
+ if (err)
175
+ goto out;
176
+ }
177
+ if (option & ETM_OPT_TS) {
178
+ err = cs_etm_set_timestamp(itr, evsel, i);
179
+ if (err)
180
+ goto out;
181
+ }
182
+ if (option & ~(ETM_OPT_CTXTID | ETM_OPT_TS))
183
+ /* Nothing else is currently supported */
184
+ goto out;
185
+ }
186
+
187
+ err = 0;
188
+out:
189
+ perf_cpu_map__put(online_cpus);
190
+ return err;
191
+}
42192
43193 static int cs_etm_parse_snapshot_options(struct auxtrace_record *itr,
44194 struct record_opts *opts,
....@@ -62,29 +212,72 @@
62212 return 0;
63213 }
64214
215
+static int cs_etm_set_sink_attr(struct perf_pmu *pmu,
216
+ struct evsel *evsel)
217
+{
218
+ char msg[BUFSIZ], path[PATH_MAX], *sink;
219
+ struct evsel_config_term *term;
220
+ int ret = -EINVAL;
221
+ u32 hash;
222
+
223
+ if (evsel->core.attr.config2 & GENMASK(31, 0))
224
+ return 0;
225
+
226
+ list_for_each_entry(term, &evsel->config_terms, list) {
227
+ if (term->type != EVSEL__CONFIG_TERM_DRV_CFG)
228
+ continue;
229
+
230
+ sink = term->val.str;
231
+ snprintf(path, PATH_MAX, "sinks/%s", sink);
232
+
233
+ ret = perf_pmu__scan_file(pmu, path, "%x", &hash);
234
+ if (ret != 1) {
235
+ pr_err("failed to set sink \"%s\" on event %s with %d (%s)\n",
236
+ sink, evsel__name(evsel), errno,
237
+ str_error_r(errno, msg, sizeof(msg)));
238
+ return ret;
239
+ }
240
+
241
+ evsel->core.attr.config2 |= hash;
242
+ return 0;
243
+ }
244
+
245
+ /*
246
+ * No sink was provided on the command line - allow the CoreSight
247
+ * system to look for a default
248
+ */
249
+ return 0;
250
+}
251
+
65252 static int cs_etm_recording_options(struct auxtrace_record *itr,
66
- struct perf_evlist *evlist,
253
+ struct evlist *evlist,
67254 struct record_opts *opts)
68255 {
256
+ int ret;
69257 struct cs_etm_recording *ptr =
70258 container_of(itr, struct cs_etm_recording, itr);
71259 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
72
- struct perf_evsel *evsel, *cs_etm_evsel = NULL;
73
- const struct cpu_map *cpus = evlist->cpus;
74
- bool privileged = (geteuid() == 0 || perf_event_paranoid() < 0);
260
+ struct evsel *evsel, *cs_etm_evsel = NULL;
261
+ struct perf_cpu_map *cpus = evlist->core.cpus;
262
+ bool privileged = perf_event_paranoid_check(-1);
263
+ int err = 0;
75264
76265 ptr->evlist = evlist;
77266 ptr->snapshot_mode = opts->auxtrace_snapshot_mode;
78267
268
+ if (!record_opts__no_switch_events(opts) &&
269
+ perf_can_record_switch_events())
270
+ opts->record_switch_events = true;
271
+
79272 evlist__for_each_entry(evlist, evsel) {
80
- if (evsel->attr.type == cs_etm_pmu->type) {
273
+ if (evsel->core.attr.type == cs_etm_pmu->type) {
81274 if (cs_etm_evsel) {
82275 pr_err("There may be only one %s event\n",
83276 CORESIGHT_ETM_PMU_NAME);
84277 return -EINVAL;
85278 }
86
- evsel->attr.freq = 0;
87
- evsel->attr.sample_period = 1;
279
+ evsel->core.attr.freq = 0;
280
+ evsel->core.attr.sample_period = 1;
88281 cs_etm_evsel = evsel;
89282 opts->full_auxtrace = true;
90283 }
....@@ -93,6 +286,10 @@
93286 /* no need to continue if at least one event of interest was found */
94287 if (!cs_etm_evsel)
95288 return 0;
289
+
290
+ ret = cs_etm_set_sink_attr(cs_etm_pmu, cs_etm_evsel);
291
+ if (ret)
292
+ return ret;
96293
97294 if (opts->use_clockid) {
98295 pr_err("Cannot use clockid (-k option) with %s\n",
....@@ -202,32 +399,39 @@
202399
203400 /*
204401 * In the case of per-cpu mmaps, we need the CPU on the
205
- * AUX event.
402
+ * AUX event. We also need the contextID in order to be notified
403
+ * when a context switch happened.
206404 */
207
- if (!cpu_map__empty(cpus))
208
- perf_evsel__set_sample_bit(cs_etm_evsel, CPU);
405
+ if (!perf_cpu_map__empty(cpus)) {
406
+ evsel__set_sample_bit(cs_etm_evsel, CPU);
407
+
408
+ err = cs_etm_set_option(itr, cs_etm_evsel,
409
+ ETM_OPT_CTXTID | ETM_OPT_TS);
410
+ if (err)
411
+ goto out;
412
+ }
209413
210414 /* Add dummy event to keep tracking */
211415 if (opts->full_auxtrace) {
212
- struct perf_evsel *tracking_evsel;
213
- int err;
416
+ struct evsel *tracking_evsel;
214417
215418 err = parse_events(evlist, "dummy:u", NULL);
216419 if (err)
217
- return err;
420
+ goto out;
218421
219
- tracking_evsel = perf_evlist__last(evlist);
422
+ tracking_evsel = evlist__last(evlist);
220423 perf_evlist__set_tracking_event(evlist, tracking_evsel);
221424
222
- tracking_evsel->attr.freq = 0;
223
- tracking_evsel->attr.sample_period = 1;
425
+ tracking_evsel->core.attr.freq = 0;
426
+ tracking_evsel->core.attr.sample_period = 1;
224427
225428 /* In per-cpu case, always need the time of mmap events etc */
226
- if (!cpu_map__empty(cpus))
227
- perf_evsel__set_sample_bit(tracking_evsel, TIME);
429
+ if (!perf_cpu_map__empty(cpus))
430
+ evsel__set_sample_bit(tracking_evsel, TIME);
228431 }
229432
230
- return 0;
433
+out:
434
+ return err;
231435 }
232436
233437 static u64 cs_etm_get_config(struct auxtrace_record *itr)
....@@ -236,11 +440,11 @@
236440 struct cs_etm_recording *ptr =
237441 container_of(itr, struct cs_etm_recording, itr);
238442 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
239
- struct perf_evlist *evlist = ptr->evlist;
240
- struct perf_evsel *evsel;
443
+ struct evlist *evlist = ptr->evlist;
444
+ struct evsel *evsel;
241445
242446 evlist__for_each_entry(evlist, evsel) {
243
- if (evsel->attr.type == cs_etm_pmu->type) {
447
+ if (evsel->core.attr.type == cs_etm_pmu->type) {
244448 /*
245449 * Variable perf_event_attr::config is assigned to
246450 * ETMv3/PTM. The bit fields have been made to match
....@@ -249,7 +453,7 @@
249453 * drivers/hwtracing/coresight/coresight-perf.c for
250454 * details.
251455 */
252
- config = evsel->attr.config;
456
+ config = evsel->core.attr.config;
253457 break;
254458 }
255459 }
....@@ -275,6 +479,8 @@
275479 config_opts = cs_etm_get_config(itr);
276480 if (config_opts & BIT(ETM_OPT_CYCACC))
277481 config |= BIT(ETM4_CFG_BIT_CYCACC);
482
+ if (config_opts & BIT(ETM_OPT_CTXTID))
483
+ config |= BIT(ETM4_CFG_BIT_CTXTID);
278484 if (config_opts & BIT(ETM_OPT_TS))
279485 config |= BIT(ETM4_CFG_BIT_TS);
280486 if (config_opts & BIT(ETM_OPT_RETSTK))
....@@ -285,15 +491,15 @@
285491
286492 static size_t
287493 cs_etm_info_priv_size(struct auxtrace_record *itr __maybe_unused,
288
- struct perf_evlist *evlist __maybe_unused)
494
+ struct evlist *evlist __maybe_unused)
289495 {
290496 int i;
291497 int etmv3 = 0, etmv4 = 0;
292
- struct cpu_map *event_cpus = evlist->cpus;
293
- struct cpu_map *online_cpus = cpu_map__new(NULL);
498
+ struct perf_cpu_map *event_cpus = evlist->core.cpus;
499
+ struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
294500
295501 /* cpu map is not empty, we have specific CPUs to work with */
296
- if (!cpu_map__empty(event_cpus)) {
502
+ if (!perf_cpu_map__empty(event_cpus)) {
297503 for (i = 0; i < cpu__max_cpu(); i++) {
298504 if (!cpu_map__has(event_cpus, i) ||
299505 !cpu_map__has(online_cpus, i))
....@@ -317,25 +523,12 @@
317523 }
318524 }
319525
320
- cpu_map__put(online_cpus);
526
+ perf_cpu_map__put(online_cpus);
321527
322528 return (CS_ETM_HEADER_SIZE +
323529 (etmv4 * CS_ETMV4_PRIV_SIZE) +
324530 (etmv3 * CS_ETMV3_PRIV_SIZE));
325531 }
326
-
327
-static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX] = {
328
- [CS_ETM_ETMCCER] = "mgmt/etmccer",
329
- [CS_ETM_ETMIDR] = "mgmt/etmidr",
330
-};
331
-
332
-static const char *metadata_etmv4_ro[CS_ETMV4_PRIV_MAX] = {
333
- [CS_ETMV4_TRCIDR0] = "trcidr/trcidr0",
334
- [CS_ETMV4_TRCIDR1] = "trcidr/trcidr1",
335
- [CS_ETMV4_TRCIDR2] = "trcidr/trcidr2",
336
- [CS_ETMV4_TRCIDR8] = "trcidr/trcidr8",
337
- [CS_ETMV4_TRCAUTHSTATUS] = "mgmt/trcauthstatus",
338
-};
339532
340533 static bool cs_etm_is_etmv4(struct auxtrace_record *itr, int cpu)
341534 {
....@@ -377,7 +570,7 @@
377570
378571 static void cs_etm_get_metadata(int cpu, u32 *offset,
379572 struct auxtrace_record *itr,
380
- struct auxtrace_info_event *info)
573
+ struct perf_record_auxtrace_info *info)
381574 {
382575 u32 increment;
383576 u64 magic;
....@@ -442,15 +635,15 @@
442635
443636 static int cs_etm_info_fill(struct auxtrace_record *itr,
444637 struct perf_session *session,
445
- struct auxtrace_info_event *info,
638
+ struct perf_record_auxtrace_info *info,
446639 size_t priv_size)
447640 {
448641 int i;
449642 u32 offset;
450643 u64 nr_cpu, type;
451
- struct cpu_map *cpu_map;
452
- struct cpu_map *event_cpus = session->evlist->cpus;
453
- struct cpu_map *online_cpus = cpu_map__new(NULL);
644
+ struct perf_cpu_map *cpu_map;
645
+ struct perf_cpu_map *event_cpus = session->evlist->core.cpus;
646
+ struct perf_cpu_map *online_cpus = perf_cpu_map__new(NULL);
454647 struct cs_etm_recording *ptr =
455648 container_of(itr, struct cs_etm_recording, itr);
456649 struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu;
....@@ -458,15 +651,15 @@
458651 if (priv_size != cs_etm_info_priv_size(itr, session->evlist))
459652 return -EINVAL;
460653
461
- if (!session->evlist->nr_mmaps)
654
+ if (!session->evlist->core.nr_mmaps)
462655 return -EINVAL;
463656
464657 /* If the cpu_map is empty all online CPUs are involved */
465
- if (cpu_map__empty(event_cpus)) {
658
+ if (perf_cpu_map__empty(event_cpus)) {
466659 cpu_map = online_cpus;
467660 } else {
468661 /* Make sure all specified CPUs are online */
469
- for (i = 0; i < cpu_map__nr(event_cpus); i++) {
662
+ for (i = 0; i < perf_cpu_map__nr(event_cpus); i++) {
470663 if (cpu_map__has(event_cpus, i) &&
471664 !cpu_map__has(online_cpus, i))
472665 return -EINVAL;
....@@ -475,7 +668,7 @@
475668 cpu_map = event_cpus;
476669 }
477670
478
- nr_cpu = cpu_map__nr(cpu_map);
671
+ nr_cpu = perf_cpu_map__nr(cpu_map);
479672 /* Get PMU type as dynamically assigned by the core */
480673 type = cs_etm_pmu->type;
481674
....@@ -492,7 +685,7 @@
492685 if (cpu_map__has(cpu_map, i))
493686 cs_etm_get_metadata(i, &offset, itr, info);
494687
495
- cpu_map__put(online_cpus);
688
+ perf_cpu_map__put(online_cpus);
496689
497690 return 0;
498691 }
....@@ -630,11 +823,11 @@
630823 {
631824 struct cs_etm_recording *ptr =
632825 container_of(itr, struct cs_etm_recording, itr);
633
- struct perf_evsel *evsel;
826
+ struct evsel *evsel;
634827
635828 evlist__for_each_entry(ptr->evlist, evsel) {
636
- if (evsel->attr.type == ptr->cs_etm_pmu->type)
637
- return perf_evsel__disable(evsel);
829
+ if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
830
+ return evsel__disable(evsel);
638831 }
639832 return -EINVAL;
640833 }
....@@ -643,11 +836,11 @@
643836 {
644837 struct cs_etm_recording *ptr =
645838 container_of(itr, struct cs_etm_recording, itr);
646
- struct perf_evsel *evsel;
839
+ struct evsel *evsel;
647840
648841 evlist__for_each_entry(ptr->evlist, evsel) {
649
- if (evsel->attr.type == ptr->cs_etm_pmu->type)
650
- return perf_evsel__enable(evsel);
842
+ if (evsel->core.attr.type == ptr->cs_etm_pmu->type)
843
+ return evsel__enable(evsel);
651844 }
652845 return -EINVAL;
653846 }
....@@ -665,21 +858,6 @@
665858
666859 zfree(&ptr->wrapped);
667860 free(ptr);
668
-}
669
-
670
-static int cs_etm_read_finish(struct auxtrace_record *itr, int idx)
671
-{
672
- struct cs_etm_recording *ptr =
673
- container_of(itr, struct cs_etm_recording, itr);
674
- struct perf_evsel *evsel;
675
-
676
- evlist__for_each_entry(ptr->evlist, evsel) {
677
- if (evsel->attr.type == ptr->cs_etm_pmu->type)
678
- return perf_evlist__enable_event_idx(ptr->evlist,
679
- evsel, idx);
680
- }
681
-
682
- return -EINVAL;
683861 }
684862
685863 struct auxtrace_record *cs_etm_record_init(int *err)
....@@ -701,6 +879,7 @@
701879 }
702880
703881 ptr->cs_etm_pmu = cs_etm_pmu;
882
+ ptr->itr.pmu = cs_etm_pmu;
704883 ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options;
705884 ptr->itr.recording_options = cs_etm_recording_options;
706885 ptr->itr.info_priv_size = cs_etm_info_priv_size;
....@@ -710,61 +889,10 @@
710889 ptr->itr.snapshot_finish = cs_etm_snapshot_finish;
711890 ptr->itr.reference = cs_etm_reference;
712891 ptr->itr.free = cs_etm_recording_free;
713
- ptr->itr.read_finish = cs_etm_read_finish;
892
+ ptr->itr.read_finish = auxtrace_record__read_finish;
714893
715894 *err = 0;
716895 return &ptr->itr;
717896 out:
718897 return NULL;
719
-}
720
-
721
-static FILE *cs_device__open_file(const char *name)
722
-{
723
- struct stat st;
724
- char path[PATH_MAX];
725
- const char *sysfs;
726
-
727
- sysfs = sysfs__mountpoint();
728
- if (!sysfs)
729
- return NULL;
730
-
731
- snprintf(path, PATH_MAX,
732
- "%s" CS_BUS_DEVICE_PATH "%s", sysfs, name);
733
-
734
- if (stat(path, &st) < 0)
735
- return NULL;
736
-
737
- return fopen(path, "w");
738
-
739
-}
740
-
741
-static int __printf(2, 3) cs_device__print_file(const char *name, const char *fmt, ...)
742
-{
743
- va_list args;
744
- FILE *file;
745
- int ret = -EINVAL;
746
-
747
- va_start(args, fmt);
748
- file = cs_device__open_file(name);
749
- if (file) {
750
- ret = vfprintf(file, fmt, args);
751
- fclose(file);
752
- }
753
- va_end(args);
754
- return ret;
755
-}
756
-
757
-int cs_etm_set_drv_config(struct perf_evsel_config_term *term)
758
-{
759
- int ret;
760
- char enable_sink[ENABLE_SINK_MAX];
761
-
762
- snprintf(enable_sink, ENABLE_SINK_MAX, "%s/%s",
763
- term->val.drv_cfg, "enable_sink");
764
-
765
- ret = cs_device__print_file(enable_sink, "%d", 1);
766
- if (ret < 0)
767
- return ret;
768
-
769
- return 0;
770898 }